Solución Tp 01

Tp 1 - Tweets sobre covid-19. Buscando patrones interesantes.

Librerías

library("ggplot2")
library("readr")
library("dplyr")
library("highcharter")
library("treemap")
library("modeest")
library("GGally")
library("tidyverse")
library("hrbrthemes")
library("tidyr")
library("VIM")
library("e1071")
library("mice")
library("mongolite")

library("SnowballC")
library("tm")
library("twitteR")
library("syuzhet")

library("tidyverse")
library("lubridate")

library("RColorBrewer")
library("infotheo"); # Discretize variable

Referencia tweets

tweets <- mongo(collection = "tweets_mongo_covid19", db = "DMUBA")

Nombres de columnas

names(tweets$find())
 [1] "user_id"                 "status_id"               "created_at"              "screen_name"            
 [5] "text"                    "source"                  "is_quote"                "is_retweet"             
 [9] "favorite_count"          "retweet_count"           "quote_count"             "reply_count"            
[13] "hashtags"                "symbols"                 "urls_url"                "urls_t_co"              
[17] "urls_expanded_url"       "media_url"               "media_t_co"              "media_expanded_url"     
[21] "media_type"              "ext_media_url"           "ext_media_t_co"          "ext_media_expanded_url" 
[25] "mentions_user_id"        "mentions_screen_name"    "lang"                    "quoted_created_at"      
[29] "retweet_status_id"       "retweet_text"            "retweet_created_at"      "retweet_source"         
[33] "retweet_favorite_count"  "retweet_retweet_count"   "retweet_user_id"         "retweet_screen_name"    
[37] "retweet_name"            "retweet_followers_count" "retweet_friends_count"   "retweet_statuses_count" 
[41] "retweet_verified"        "geo_coords"              "coords_coords"           "bbox_coords"            
[45] "status_url"              "name"                    "location"                "description"            
[49] "protected"               "followers_count"         "friends_count"           "listed_count"           
[53] "statuses_count"          "favourites_count"        "account_created_at"      "verified"               
[57] "profile_banner_url"      "profile_background_url"  "profile_image_url"       "retweet_location"       
[61] "retweet_description"     "quoted_status_id"        "quoted_text"             "quoted_source"          
[65] "quoted_favorite_count"   "quoted_retweet_count"    "quoted_user_id"          "quoted_screen_name"     
[69] "quoted_name"             "quoted_followers_count"  "quoted_friends_count"    "quoted_statuses_count"  
[73] "quoted_location"         "quoted_description"      "quoted_verified"         "url"                    
[77] "place_url"               "place_name"              "place_full_name"         "place_type"             
[81] "country"                 "country_code"            "lat"                     "lng"                    
[85] "display_text_width"      "reply_to_status_id"      "reply_to_user_id"        "reply_to_screen_name"   

Tipos de tweets

t <- mongo(db="DMUBA", collection="tweet_type")
tweets_types <- t$find()
cat("Cantidades de tweets por tipo \n\n")
Cantidades de tweets por tipo 
cat("\t* Tweets: ", nrow(tweets_types), "\n")
    * Tweets:  28907 
cat("\t* Solo RT: ", nrow(tweets_types[tweets_types$is_retweet & !tweets_types$is_quote,]), "\n")
    * Solo RT:  17870 
cat("\t* Solo QT: ", nrow(tweets_types[!tweets_types$is_retweet & tweets_types$is_quote,]), "\n")
    * Solo QT:  1789 
cat("\t* RT y QT: ", nrow(tweets_types[tweets_types$is_retweet & tweets_types$is_quote,]), "\n")
    * RT y QT:  3416 
cat("\t* TW originales: ", nrow(tweets_types[!tweets_types$is_retweet & !tweets_types$is_quote,]), "\n")
    * TW originales:  5832 
tweets_types$tipo <- ""
tweets_types[tweets_types$is_retweet & !tweets_types$is_quote,]$tipo <- "Solo RT"
tweets_types[!tweets_types$is_retweet & tweets_types$is_quote,]$tipo <- "Solo QT"
tweets_types[tweets_types$is_retweet & tweets_types$is_quote,]$tipo <- "RQ y RT"
tweets_types[!tweets_types$is_retweet & !tweets_types$is_quote,]$tipo <- "Original"
# names = c('Solo RT', 'Solo QT', 'RT + QT', 'Original')
# cantidades = c(nrow(tweets_types[tweets_types$is_retweet & !tweets_types$is_quote,]),
#                nrow(tweets_types[!tweets_types$is_retweet & tweets_types$is_quote,]),
#                nrow(tweets_types[tweets_types$is_retweet & tweets_types$is_quote,]),
#                nrow(tweets_types[!tweets_types$is_retweet & !tweets_types$is_quote,])
#               )
#                
grafico_tipos <- data.frame(table(tweets_types$tipo))

# barplot(sort(grafico_tipos$Freq, decreasing=TRUE), legend.text=grafico_tipos$Var1, col=c('red','green','blue','brown'))
# barplot(height=sort(grafico_tipos$Freq, decreasing=TRUE), names=grafico_tipos$Var1, col=rgb(0.2,0.4,0.6,0.6) )

names(grafico_tipos) <- c("Tipos", "Cantidad")

coul <- brewer.pal(5, "Set2") 
barplot(height=sort(grafico_tipos$Cantidad, decreasing=TRUE), names=grafico_tipos$Tipos, col=coul )


# coul <- brewer.pal(5, "Set2") 

png(filename="tipo_tweet.png", width=1000, bg="white")
ggplot(grafico_tipos, aes(x=reorder(Tipos, Cantidad), y=Cantidad, fill=Tipos)) + 
    geom_bar(stat="identity") +
    scale_fill_brewer(palette="Set2") +
    labs(
      title = "",
      subtitle = "",
      caption = "",
      tag = ""
      ) +
    xlab("") +
    ylab("") +
    theme(plot.title = element_text(hjust = 0.5), 
          axis.text=element_text(size=12),
          axis.text.y = element_text( margin = margin(10, 10, 10, 10)),
          axis.title.x = element_text(margin = margin(t = 10, r = 10, b = 10, l = 10)),
          legend.text=element_text(size=12)) +
    coord_flip()
dev.off()
null device 
          1 

% de Verificados según tipo de tweet


tweets <- mongo(db="DMUBA", collection="tweet_completo_estadisticas")
numericos <- tweets$find()

# Tipos
numericos$Tipo <- ""
numericos[numericos$is_retweet & !numericos$is_quote,]$Tipo <- "Solo RT"
numericos[!numericos$is_retweet & numericos$is_quote,]$Tipo <- "Solo QT"
numericos[numericos$is_retweet & numericos$is_quote,]$Tipo <- "QT y RT"
numericos[!numericos$is_retweet & !numericos$is_quote,]$Tipo <- "Original"

numericos$verificado <- F
numericos[numericos$Tipo == "Solo QT",]$verificado <-  numericos[numericos$Tipo == "Solo QT",]$quoted_verified
numericos[numericos$Tipo == "Original",]$verificado <-  numericos[numericos$Tipo == "Original",]$verified
numericos[numericos$Tipo == "Solo RT",]$verificado <-  numericos[numericos$Tipo == "Solo RT",]$retweet_verified
numericos[numericos$Tipo == "QT y RT",]$verificado <-  numericos[numericos$Tipo == "QT y RT",]$retweet_verified

numericos$verificado_grafico <- ""
numericos[numericos$verificado,]$verificado_grafico <- "Si"
numericos[!numericos$verificado,]$verificado_grafico <- "No"

png(filename="tipo_x_tweet_grid2.png", width=1000, bg="white")
ggplot(data=numericos, aes(x=verificado_grafico, fill=Tipo)) + 
        scale_fill_brewer(palette="Set2") +
        geom_bar() +
        labs(
          title = "",
          subtitle = "",
          caption = "",
          tag = ""
          ) +
        xlab("") +
        ylab("") +
        theme(plot.title = element_text(hjust = 0.5), 
              axis.text=element_text(size=10),
              axis.text.y = element_text( margin = margin(10, 10, 10, 10)),
              axis.title.x = element_text(margin = margin(t = 10, r = 10, b = 10, l = 10)),
              legend.text=element_text(size=10),
              aspect.ratio=19/19) +
        facet_wrap(~ Tipo, nrow=2)
dev.off()
null device 
          1 
ggplot(data=tweets_types, aes(x=verified, fill=tipo)) + 
  geom_bar() + facet_wrap(~ tipo, nrow=2)

Hay más usuarios verificados en el contenido nuevo. A su vez, hay más verificos en el contenido citado. Eso habla de que un usuario verificado crea un contenido de mayor calidad (Más difundido y novedoso).

Mientras que el usuario difusor y los retweets, si bien aumentan el alcance de los tweets, no tienen una calidad alta.

Tweets según tiempo

t <- mongo(db="DMUBA", collection="fechas")
tweets_fechas <- t$find()
summary(tweets_fecha)
     fecha                           t                                         tc       
 Min.   :2020-04-24 23:52:38   Min.   :2020-04-24 23:52:38   2020-05-02 01:44:00: 1049  
 1st Qu.:2020-05-02 01:46:45   1st Qu.:2020-05-02 01:46:45   2020-05-02 01:40:00: 1043  
 Median :2020-05-04 20:30:15   Median :2020-05-04 20:30:15   2020-05-02 01:45:00: 1041  
 Mean   :2020-05-06 12:24:30   Mean   :2020-05-06 12:24:30   2020-05-02 01:43:00: 1012  
 3rd Qu.:2020-05-10 12:02:52   3rd Qu.:2020-05-10 12:02:52   2020-05-02 01:41:00:  990  
 Max.   :2020-05-15 18:24:13   Max.   :2020-05-15 18:24:13   2020-05-02 01:48:00:  990  
                                                             (Other)            :22782  
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
                                                                                        
 fecha_str.Length  fecha_str.Class  fecha_str.Mode
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 1          -none-     character                  
 [ reached getOption("max.print") -- omitted 28657 rows ]

En un primer intento de graficar, vemos que los datos estan distribuidos de una forma particular. La primera pregunta es ¿Hay alguna fecha que presentó una cantidad anómala de datos?

El 2 de mayo lo es. Sin embargo, no fue un día en el que aconteció alguna cosa. Ni es feriado (1/5), ni fue día de anuncios (25/4).

# plot(tweets_fecha$fecha)
# barplot(table(as.Date(tweets_fecha$fecha)))
f<- data.frame(table(as.Date(tweets_fecha$fecha)))
ggplot(data=f, aes(x=Freq)) + 
  geom_histogram(fill="#69b3a2", color="#e9ecef", alpha=0.9) +
    ggtitle("Bin size = 3") +
    theme_ipsum() +
    theme(
      plot.title = element_text(size=15)
    )

Agrupando en fracciones menos, 5 minutos, vemos que lo que aconteció fue una ventana de captura de datos desigual. Al reducir la ventana de tiempo, vemos que hay una distribución más uniforme. Igualmente sigue planteandose la pregunta, podríamos analizarlo de a minutos, o con diferencias porcentuales, para ver si realmente hya algo ahí.

tweets_fecha$t <- ymd_hms(tweets_fecha$fecha)
tweets_fecha$tc <- cut(tweets_fecha$t, breaks = "5 min")  
cant_5_min <- count(tweets_fecha, tc)
barplot(cant_5_min$n, legend.text=cant_5_min$tc)

## Tweets por fecha
tweets_fecha$t <- ymd_hms(tweets_fecha$fecha)

# Por minuto está más equilibrado)
tweets_fecha$tc <- cut(tweets_fecha$t, breaks = "1 min")  
cant_5_min <- count(tweets_fecha, tc)
barplot(cant_5_min$n)

La variable temporal parece ser arbitraria.

Algo a seguir investigando es la ventana temporal entre: * Fecha creada y fecha de creacion del retweet * Fecha creada y fecha de creacion del quoted

library(ggplot2)
library(dplyr)
library("plotly")

Attaching package: 㤼㸱plotly㤼㸲

The following object is masked from 㤼㸱package:ggplot2㤼㸲:

    last_plot

The following object is masked from 㤼㸱package:stats㤼㸲:

    filter

The following object is masked from 㤼㸱package:graphics㤼㸲:

    layout
library(hrbrthemes)
# tweets_fecha$fecha
tweets_fecha$fecha_str <-  lapply(tweets_fecha$tc, as.character)
b <- as.POSIXlt(strptime(tweets_fecha$tc, format = "%H:%M:%S"))
cant_5_min$fecha <- as.Date(cant_5_min$tc)
cant_5_min$hora <-  format(strptime(cant_5_min$tc, format = "%Y-%m-%d %H:%M:%S"), format="%H:%M:%S")

p <- cant_5_min %>%
  ggplot( aes(x=reorder(hora, hora), y=n, fill=n)) + 
    geom_bar(stat="identity") +
    scale_fill_gradient2(low='red', mid='snow3', high='darkgreen', space='Lab') +
        labs(
          title = "",
          subtitle = "",
          caption = "",
          tag = ""
          ) +
        xlab("") +
        ylab("") +
    theme(axis.title.x=element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank(),
        axis.title.y=element_blank(),
        axis.text.y=element_blank(),
        axis.ticks.y=element_blank()) +
    facet_wrap(~ fecha, nrow=4)

png(filename="tipo_x_tweet.png", width=1000, bg="white")
p
dev.off()
null device 
          1 
# Turn it interactive with ggplotly
p <- ggplotly(p)
argument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NAargument is not numeric or logical: returning NA

p

Texto

ggplot(tweets_text, aes(x=cantChars)) +
  geom_density(fill="#69b3a2", color="#e9ecef", alpha=0.8) +
  ggtitle("Cantidad de catacteres por tweet") +
  theme_ipsum()

Menos numeros y simbolos


tweets_text.df2$text <- gsub("[[:punct:]]","",tweets_text.df2$text)
tweets_text.df2$text <- gsub("\\w*[0-9]+\\w*\\s*", "",tweets_text.df2$text)
tweets_text.df2$cantChars <- nchar(tweets_text.df2$text)
ggplot(tweets_text.df2, aes(x=cantChars)) +
  geom_density(fill="#69b3a2", color="#e9ecef", alpha=0.8) +
  ggtitle("Sin caracteres especiales y numeros") +
  theme_ipsum()

Hashtags

Cantidad de nulos

tweets_hashes_null <- tweets$find('{"hashtags":{"$elemMatch":{"$in":[null], "$exists":true}}}')
print(nrow(tweets_hashes))
[1] 9636

Preprocesamiento

tweets_count <- mongo(db='DMUBA', collection='tweet_count_hashtags')
tweets_count <- tweets_count$find()
tweets_count$hashtag_2 <- gsub("[[:punct:]]","",tweets_count$hashtag);
tweets_count$hashtag_2 <- gsub("[^[:alnum:][:blank:]?&/\\-]", "", tweets_count$hashtag_2);
tweets_count$hashtag_2 <- iconv(tweets_count$hashtag_2,from="UTF-8",to="ASCII//TRANSLIT");
tweets_count$is_cuarentena_related <- F
for (i in cuarentena_words) {
  tweets_count$is_cuarentena_related <- ifelse(grepl(i, tweets_count$hashtag_2, fixed= T), T, tweets_count$is_cuarentena_related)
}
tweets_count$is_sex_related <- F
for (i in sex_words) {
  tweets_count$is_sex_related <- ifelse(grepl(i, tweets_count$hashtag_2, fixed= T), T, tweets_count$is_sex_related)
}

Top 20 de hashtags no relacionados a cuarentena

head(tweets_count[!tweets_count$is_cuarentena_related & !tweets_count$is_sex_related,] %>% select(2:3), n=20)
NA

Algo que me llamo la atencion: * Cuba * México, bartlett (Ministro mexicano), snte (sindicato de profesores). * Venezuela, proteccionyaccion * AFP, tenía una doble implicación fondo de pensión o agencia de prensa francesa. La primera idea de un fondo de pensiones que pudiese usarse como fondo de emergencia y que generaba polémica era interesante como reaccion al covid. Sin embargo haciendo una segunda búsqueda apartir del campo texto, vemos que un hashtag con repercusión ambigua, toca ambos temas y además fondos de pensión de otros países. Por lo que entrar en el significa mucho tiempo y poca información específica.

TODO: * Hay algo con posibilidad de ser profundizado, que es porque de cada uno, que impacto, quienes lo generaron, que influencia, fueron trending topic, cuantos días? * Argentina vs el resto (Cuba, Mexico, Chile). * Tienen que ver estos hashtags con los trending topic? mismo siendo random, llegamos a obtener parte de esa representatividad de los trending topics?

Perfils de Usuarios:

user_estadisticas <- mongo(db="DMUBA", collection="user_estadisticas")
summary(info_user)
   user_id          screen_name            name           description        followers_count    friends_count   
 Length:25435       Length:25435       Length:25435       Length:25435       Min.   :       0   Min.   :     0  
 Class :character   Class :character   Class :character   Class :character   1st Qu.:      92   1st Qu.:   184  
 Mode  :character   Mode  :character   Mode  :character   Mode  :character   Median :     313   Median :   441  
                                                                             Mean   :   12581   Mean   :  1242  
                                                                             3rd Qu.:     999   3rd Qu.:  1073  
                                                                             Max.   :18609108   Max.   :971277  
  listed_count      statuses_count    favourites_count  account_created_at               verified       user_popularity   
 Min.   :    0.00   Min.   :      1   Min.   :      0   Min.   :2007-02-15 14:03:49   Min.   :0.00001   Length:25435      
 1st Qu.:    0.00   1st Qu.:   2209   1st Qu.:   1116   1st Qu.:2011-05-13 00:01:30   1st Qu.:0.00001   Class :character  
 Median :    1.00   Median :   9386   Median :   5514   Median :2013-12-25 05:01:22   Median :0.00001   Mode  :character  
 Mean   :   51.04   Mean   :  34748   Mean   :  19285   Mean   :2014-08-19 17:22:36   Mean   :0.01444                     
 3rd Qu.:    6.00   3rd Qu.:  31359   3rd Qu.:  19238   3rd Qu.:2018-04-02 03:49:06   3rd Qu.:0.00001                     
 Max.   :57770.00   Max.   :7203370   Max.   :1265094   Max.   :2020-05-15 18:08:33   Max.   :1.00000                     
# User base
info_user <- user_estadisticas$find()
# Con log sin los que tiene 0
data_log <- as.data.frame(apply(info_user[,5:9], 2, log))
# Log con los que tiene 0
info_user[info_user == 0] <- 0.00001
data_log_1 <- as.data.frame(apply(info_user[,5:9], 2, log))

cat("Cantidad de usuarios que han twitteado: ", nrow(info_user))
Cantidad de usuarios que han twitteado:  25435

# ggpairs(data_log)
# ggpairs(info_user[,1:5])

boxplot(info_user[,5:9])


# Con 0's
boxplot(data_log)

# Con 0.0000001's
boxplot(data_log_1)


# 
# info_user$verificado <- ifelse(info_user$verified, "Verificados", "Sin verificar")
# info_user$verificado <- as.factor(info_user$verificado)

Todo: * Juntar usuarios finales, usuarios que fueron replicados * Que hace que un usuario sea más divulgado? Hay alguna medida de relevancia de un usuario? Aquellos más populares (Segun que criterio?) son de que tipo? Instituciones, usuarios comunes, bots? Que tan activos son? Influye eso? Desde que dispositivo lo hacen? Que tipo de texto crean? Que hashtags usan? De que regiones son? Hay algo interesante ahí? Hay predominio de algun pais? Hay paises donde se usa más el twitter?

Tipos de usuarios:


user_tweets_estadisticas <- mongo(db="DMUBA", collection="user_tweets_estadisticas")
# User base
info_user <- user_tweets_estadisticas$find()
summary(info_user$is_none)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.000   1.000   1.000   1.137   1.000  31.000 
info_user[info_user == 0] <- 0.00001
data_log_1 <- as.data.frame(apply(info_user[,3:7], 2, log))
# Plot de grupos

plot(sort(data_log_1$is_rt))

plot(sort(data_log_1$is_only_rt))

plot(sort(data_log_1$is_only_qt))

plot(sort(data_log_1$is_none))

plot(sort(data_log_1$is_qt))

TODO: Binning con esto? Alinear distintos grupos en cada categoria? Solo clasificarlos?

Usuarios con más tweets

head(info_user[order(info_user$count, decreasing = T),])

Curiosamente, los usuarios finales con más tweets son creadores. serán bots?

Categorizar

info_user$tipo <- ifelse(info_user$is_none > info_user$is_only_rt + info_user$is_only_rt, "Creador", "Difusor")
barplot(table(info_user$tipo))
info_user_graf <- data.frame(table(info_user$tipo))
names(info_user_graf) <- c("Tipo_usuario", "Cantidad")

png(filename="tipo_usuario_creacion.png", width=1000, bg="white")
ggplot(info_user_graf, aes(x=reorder(Tipo_usuario , Cantidad), y=Cantidad, fill=Tipo_usuario)) + 
    geom_bar(stat="identity") +
    scale_fill_brewer(palette="Set2") +
    labs(
      title = "",
      subtitle = "",
      caption = "",
      tag = ""
      ) +
    xlab("") +
    ylab("") +
    theme(plot.title = element_text(hjust = 0.5), 
          axis.text=element_text(size=14),
          axis.text.y = element_text( margin = margin(10, 10, 10, 10)),
          axis.title.x = element_text(margin = margin(t = 10, r = 10, b = 10, l = 10)),
              legend.text=element_text(size=14),
    # theme(plot.title = element_text(hjust = 0.5), 
    #       axis.title.x = element_text(margin = margin(t = 10, r = 10, b = 10, l = 10))
          ) +
    coord_flip()
dev.off()
png 
  2 

Usuarios según popularidad

user_estadisticas <- mongo(db="DMUBA", collection="user_estadisticas")
info_user <- user_estadisticas$find()

data_log <- as.data.frame(apply(info_user[,5:9], 2, log10))
info_user[info_user == 0] <- 0.00001
info_user[is.na(info_user)] <- 0.0001
data_log_1 <- as.data.frame(apply(info_user[,5:9], 2, log10))

Correllations

ggpairs(data_log_1)

There were 25 warnings (use warnings() to see them)
bin_eq_freq <- discretize(data_log_1$followers_count,"equalfreq", 20)
bin_eq_freq$followers_count = data_log_1$followers_count

# Por cada bin calculamos la media y reemplazamos en el atributo suavizado
for(bin in 1:20){
  bin_eq_freq$suavizado[ bin_eq_freq$X==bin] = mean(bin_eq_freq$followers_count[ bin_eq_freq$X==bin])
}

# grafico Sepal.Width ordenado de menor a mayor
plot(sort(data_log_1$followers_count) , type = "p", col="red", 
     ylab = "followers_count", xlab = "Observaciones", main = "Dato original vs suavizado")
# Agrego la serie de la variable media 
lines(sort(bin_eq_freq$suavizado),
      type = "p", col="blue")
legend("topleft", legend=c("Original", "Suavizado"), col=c("red", "blue"), lty=1)



bin_eq_freq <- discretize(data_log_1$listed_count,"equalfreq", 20)
bin_eq_freq$listed_count = data_log_1$listed_count

# Por cada bin calculamos la media y reemplazamos en el atributo suavizado
for(bin in 1:20){
  bin_eq_freq$suavizado[ bin_eq_freq$X==bin] = mean(bin_eq_freq$listed_count[ bin_eq_freq$X==bin])
}

# grafico Sepal.Width ordenado de menor a mayor
plot(sort(data_log_1$listed_count) , type = "p", col="red", 
     ylab = "listed_count", xlab = "Observaciones", main = "Dato original vs suavizado")
# Agrego la serie de la variable media 
lines(sort(bin_eq_freq$suavizado),
      type = "p", col="blue")
legend("topleft", legend=c("Original", "Suavizado"), col=c("red", "blue"), lty=1)

Usuarios según actividad

# no_na_data <- data_log_1[!is.na(data_log_1$statuses_count),]
bin_eq_freq <- discretize(data_log_1$statuses_count,"equalwidth", 5)
bin_eq_freq$statuses_count = data_log_1$statuses_count

# Por cada bin calculamos la media y reemplazamos en el atributo suavizado
for(bin in 1:5){
  bin_eq_freq$suavizado[ bin_eq_freq$X==bin] = mean(bin_eq_freq$statuses_count[ bin_eq_freq$X==bin])
}

# grafico Sepal.Width ordenado de menor a mayor
plot(sort(data_log_1$statuses_count) , type = "p", col="red", 
     ylab = "statuses_count", xlab = "Observaciones", main = "Dato original vs suavizado")
# Agrego la serie de la variable media 
lines(sort(bin_eq_freq$suavizado),
      type = "p", col="blue")
legend("topleft", legend=c("Original", "Suavizado"), col=c("red", "blue"), lty=1)


# no_na_data <- data_log_1[!is.na(data_log_1$favourites_count),]
bin_eq_freq <- discretize(data_log_1$favourites_count,"equalwidth", 10)
bin_eq_freq$favourites_count = data_log_1$favourites_count

# Por cada bin calculamos la media y reemplazamos en el atributo suavizado
for(bin in 1:10){
  bin_eq_freq$suavizado[ bin_eq_freq$X==bin] = mean(bin_eq_freq$favourites_count[ bin_eq_freq$X==bin])
}

# grafico Sepal.Width ordenado de menor a mayor
plot(sort(data_log_1$favourites_count) , type = "p", col="red", 
     ylab = "favourites_count", xlab = "Observaciones", main = "Dato original vs suavizado")
# Agrego la serie de la variable media 
lines(sort(bin_eq_freq$suavizado),
      type = "p", col="blue")
legend("topleft", legend=c("Original", "Suavizado"), col=c("red", "blue"), lty=1)

TODO: * Dentro de los creadores, alguno fue retweteado? Citado? Cual es el impacto de los creadores? * Dentro de los difusores, que impacto tienen? Que relevancia tienen los creadores originales? Cuando tweets fueron amplificados más de una vez en el grupo de twitteros finales? * Es muy simplista esto? Funciona? Hay dispositivos privilegiados? Usan software para publicaciones los creadores? Los difusores? * Entre los creadores, hay verificados? Hay alguna forma de evaluar la confiabilidad o la veracidad de lo que dicen? * Entre los difusores, hay fake news? Hay difusion indiscriminada? Hay relacion entre algun par de usuarios? Hay alguna persona que tiene más difusion que otra? s

Paises


tweets <- mongo(collection = "tweets_lower", db = "DMUBA")

df_location <- tweets$aggregate('[{
            "$project": { 
                "_id": "$_id",
                "location": "$location",
                "retweet_location": "$retweet_location",
                "quoted_location": "$quoted_location",
                "country_code": "$country_code",
                "country": "$country",
                "lat": "$lat",
                "lng": "$lng"
            }
        }
    ]')
nombre_location <- c("location", "retweet", "quoted", "country_code", "country", "lat", "lng")
cant_unique <- c( length(unique(df_location$location))
                  ,length(unique(df_location$retweet_location))
                  ,length(unique(df_location$quoted_location))
                  ,length(unique(df_location$country_code))
                  ,length(unique(df_location$country))
                  ,length(unique(df_location$lat))
                  ,length(unique(df_location$lng)))
cant_na <- c( nrow(df_location[is.na(df_location$location),])
              , nrow(df_location[is.na(df_location$retweet_location),])
              , nrow(df_location[is.na(df_location$quoted_location),])
              , nrow(df_location[is.na(df_location$country_code),])
              , nrow(df_location[is.na(df_location$country),])
              , nrow(df_location[is.na(df_location$lat),])
              , nrow(df_location[is.na(df_location$lng),])
)
df <- do.call(rbind, Map(data.frame, A=nombre_location, B=cant_unique, C=cant_na))
names(df)[1] <- "Atributo"
names(df)[2] <- "Unique"
names(df)[3] <- "Na"

df$porcentaje_na <- df$Na / nrow(df_location) * 100
There were 22 warnings (use warnings() to see them)
# png(filename="location_porc_na.png", width=1000, bg="white")
ggplot(df, aes(x=reorder(Atributo, porcentaje_na), y=porcentaje_na, fill=Atributo)) + 
  geom_bar(stat="identity") +
  scale_fill_brewer(palette="Set2") +
  labs(
    title = "",
    subtitle = "",
    caption = "",
    tag = ""
  ) +
  xlab("") +
  ylab("") +
  theme(plot.title = element_text(hjust = 0.5), 
        axis.text=element_text(size=14),
        axis.text.y = element_text( margin = margin(10, 10, 10, 10)),
        axis.title.x = element_text(margin = margin(t = 10, r = 10, b = 10, l = 10)),
        legend.text=element_text(size=14),
        aspect.ratio = 1/1
        ) +
  coord_flip()
# dev.off()

paises_en <- read.csv("C:\\Users\\Lucas\\Desktop\\2019\\Data minning\\DataMiningUba2020\\Tps\\Tp1\\countries.en.csv", header = T, sep = ';')
paises_es <- read.csv("C:\\Users\\Lucas\\Desktop\\2019\\Data minning\\DataMiningUba2020\\Tps\\Tp1\\countries.es.csv", header = T, sep = ';')

head(paises_en)
head(paises_es)
paises_es$Pais <- trimws(paises_es$Pais, which = "both")
paises_es$Codigo <- trimws(paises_es$Codigo, which = "both")
paises_es$Region <- trimws(paises_es$Region, which = "both")
paises_es$Continente <- trimws(paises_es$Continente, which = "both")
df_location$country_2 <- df_location$country
df_location$country_code_2 <- df_location$country_code
for(i in paises_en$NAME){
  print(i)
  df_location$country_2 <- ifelse(grepl(tolower(i), tolower(df_location$location), fixed= T), tolower(i), df_location$country_2)
}


for(i in paises_en$NAME){
  print(i)
  if (nrow(df_location[!is.na(df_location$country_2) & df_location$country_2 == tolower(i),]) > 0) {
    # df_location$country_code_2[!is.na(df_location$country_2) & df_location$country_2 == tolower('spain')] <- as.character.factor(paises_en$ISO[paises_en$NAME == 'SPAIN'])
    # df_location$country_code_2[!is.na(df_location$country_2) & df_location$country_2 == tolower(i)] <- as.character.factor(paises_en$ISO[paises_en$NAME == i])
    df_location[!is.na(df_location$country_2) & df_location$country_2 == tolower(i),]$country_code_2 <- paises_en$ISO[paises_en$NAME == i]
  }
}
for(i in paises_es$Pais){
  print(i)
  # ifelse(grepl("Argentina", df_location$location, fixed= T), "Argentina", "")
  df_location$country_2 <- ifelse(grepl(tolower(i), tolower(df_location$location), fixed= T), tolower(i), df_location$country_2)
}

for(i in paises_es$Pais){
  print(i)
  if (nrow(df_location[!is.na(df_location$country_2) & df_location$country_2 == tolower(i),]) > 0) {
    # df_location$country_code_2[!is.na(df_location$country_2) & df_location$country_2 == tolower('spain')] <- as.character.factor(paises_en$ISO[paises_en$NAME == 'SPAIN'])
    # df_location$country_code_2[!is.na(df_location$country_2) & df_location$country_2 == tolower(i)] <- as.character.factor(paises_en$ISO[paises_en$NAME == i])
    df_location[!is.na(df_location$country_2) & df_location$country_2 == tolower(i),]$country_code_2 <- paises_es$Codigo[paises_es$Pais == i]
  }
  # df_location$country_code_2[!is.na(df_location$country_2) & df_location$country_2 == tolower(i)] <- as.character.factor(paises_es$Codigo[paises_es$Pais == i])
}

#Unimos continente


for(i in paises_es$Codigo){
  print(i)
  df_location$Region[!is.na(df_location$country_code_2) & df_location$country_code_2 == i] <- paises_es$Region[paises_es$Codigo == i]
  df_location$Continente[!is.na(df_location$country_code_2) & df_location$country_code_2 == i] <- paises_es$Continente[paises_es$Codigo == i]
}

Clasificar en noticias - politica - otros


t <- mongo(collection = "tweets_lower", db = "DMUBA")
aux <- t$aggregate('[{"$project":{"_id": "$_id","user_id":"$user_id","screen_name":"$screen_name","text":"$description"}}]')
aux$text <- tolower(aux$text)
aux$text <- gsub("http.*","",aux$text)
aux$text <- gsub("https.*","",aux$text)

# #Quitando los hashtags y usuarios en los tweets_text
# aux$text <- gsub("#\\w+","",aux$text)
aux$text <- gsub("@\\w+","",aux$text)

aux$text <- gsub("[[:punct:]]","",aux$text)
aux$text <- gsub("\\w*[0-9]+\\w*\\s*", "",aux$text)

aux$text <- gsub("[[:punct:]]","",aux$text)
aux$text <- gsub("[^[:alnum:][:blank:]?&/\\-]", "", aux$text)
aux$text <- iconv(aux$text,from="UTF-8",to="ASCII//TRANSLIT")
  
palabras_noticias <- c("noticia", "periodismo", "periodista", 'periodico', "news", 'journalist', "reportero", "programa de tv", 'television', 'Reuters ', 'elpaisamerica', 'productora', 'conductor', 'columnista', 'corresponsal', 'telesur')
aux$is_news_related <- F
for (i in palabras_noticias) {
  aux$is_news_related <- ifelse(grepl(i, aux$text, fixed= T), T, aux$is_news_related)
}
palabras_politica <- c("politico", "senador", "diputado", "alcalde", "subsecretario", "secretario", "secretaria", "presidencia", "presidente", "ministerio", "ministro", "ministra", "público", "publico", "canciller", "Partido Socialista", "PSUV", "partido del pueblo", 'asamblea nacional')
aux$is_politic_related <- F
for (i in palabras_politica) {
  aux$is_politic_related <- ifelse(grepl(i, aux$text, fixed= T), T, aux$is_politic_related)
}
# barplot(tweets$is_news_related)
# barplot(tweets$is_politic_related)
aux$tipo_user = "Normal"
aux[aux$is_news_related,]$tipo_user <- "Medio"
aux[aux$is_politic_related,]$tipo_user <- "Politica"
aux$is_news_related <- NULL
aux$is_politic_related <- NULL
aux$text <- NULL

aux[aux$tipo_user=='Politica',]
# tweets <- merge(tweets, aux, by="tweet_id")
aux %>% group_by(screen_name) %>% summarise(tipo = max(tipo_user))
# table(aux$tipo_user)
aux <- t$aggregate('[{"$project":{"_id":"$_id","user_id":"$retweet_user_id","screen_name":"$retweet_screen_name","text":"$retweet_description"}}]')
aux <- aux[!is.na(aux$screen_name),]
aux$text <- tolower(aux$text)
aux$text <- gsub("http.*","",aux$text)
aux$text <- gsub("https.*","",aux$text)

# #Quitando los hashtags y usuarios en los tweets_text
# aux$text <- gsub("#\\w+","",aux$text)
aux$text <- gsub("@\\w+","",aux$text)

aux$text <- gsub("[[:punct:]]","",aux$text)
aux$text <- gsub("\\w*[0-9]+\\w*\\s*", "",aux$text)

aux$text <- gsub("[[:punct:]]","",aux$text)
aux$text <- gsub("[^[:alnum:][:blank:]?&/\\-]", "", aux$text)
aux$text <- iconv(aux$text,from="UTF-8",to="ASCII//TRANSLIT")
  
palabras_noticias <- c("noticia", "periodismo", "periodista", 'periodico', "news", 'journalist', "reportero", "programa de tv", 'television', 'Reuters ', 'elpaisamerica', 'productora', 'conductor', 'columnista', 'corresponsal', 'telesur')
aux$is_news_related <- F
for (i in palabras_noticias) {
  aux$is_news_related <- ifelse(grepl(i, aux$text, fixed= T), T, aux$is_news_related)
}
palabras_politica <- c("politico", "senador", "diputado", "alcalde", "subsecretario", "secretario", "secretaria", "presidencia", "presidente", "ministerio", "ministro", "ministra", "público", "publico", "canciller", "Partido Socialista", "PSUV", "partido del pueblo", 'asamblea nacional')
aux$is_politic_related <- F
for (i in palabras_politica) {
  aux$is_politic_related <- ifelse(grepl(i, aux$text, fixed= T), T, aux$is_politic_related)
}
# barplot(tweets$is_news_related)
# barplot(tweets$is_politic_related)
aux$tipo_user = "Normal"
aux[aux$is_news_related,]$tipo_user <- "Medio"
aux[aux$is_politic_related,]$tipo_user <- "Politica"
aux$is_news_related <- NULL
aux$is_politic_related <- NULL
aux$text <- NULL

aux[aux$tipo_user=='Politica',]
# tweets <- merge(tweets, aux, by="tweet_id")
aux %>% group_by(screen_name) %>% summarise(tipo = max(tipo_user))
# table(aux$tipo_user)
names(user)
[1] "_id"                 "user_id"             "retweet_screen_name" "tipo_user"          
names(aux)
[1] "_id"         "user_id"     "screen_name" "tipo_user"  
LS0tDQp0aXRsZTogIlRwIDEgLSBUd2VldHMgc29icmUgY292aWQtMTkiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQoNCiMgU29sdWNpw7NuIFRwIDAxDQoNClRwIDEgLSBUd2VldHMgc29icmUgY292aWQtMTkuIA0KQnVzY2FuZG8gcGF0cm9uZXMgaW50ZXJlc2FudGVzLg0KDQojIyBMaWJyZXLDrWFzDQoNCmBgYHtyfQ0KbGlicmFyeSgiZ2dwbG90MiIpDQpsaWJyYXJ5KCJyZWFkciIpDQpsaWJyYXJ5KCJkcGx5ciIpDQpsaWJyYXJ5KCJoaWdoY2hhcnRlciIpDQpsaWJyYXJ5KCJ0cmVlbWFwIikNCmxpYnJhcnkoIm1vZGVlc3QiKQ0KbGlicmFyeSgiR0dhbGx5IikNCmxpYnJhcnkoInRpZHl2ZXJzZSIpDQpsaWJyYXJ5KCJocmJydGhlbWVzIikNCmxpYnJhcnkoInRpZHlyIikNCmxpYnJhcnkoIlZJTSIpDQpsaWJyYXJ5KCJlMTA3MSIpDQpsaWJyYXJ5KCJtaWNlIikNCmxpYnJhcnkoIm1vbmdvbGl0ZSIpDQoNCmxpYnJhcnkoIlNub3diYWxsQyIpDQpsaWJyYXJ5KCJ0bSIpDQpsaWJyYXJ5KCJ0d2l0dGVSIikNCmxpYnJhcnkoInN5dXpoZXQiKQ0KDQpsaWJyYXJ5KCJ0aWR5dmVyc2UiKQ0KbGlicmFyeSgibHVicmlkYXRlIikNCg0KbGlicmFyeSgiUkNvbG9yQnJld2VyIikNCmxpYnJhcnkoImluZm90aGVvIik7ICMgRGlzY3JldGl6ZSB2YXJpYWJsZQ0KDQpgYGANCg0KIyMgUmVmZXJlbmNpYSB0d2VldHMNCmBgYHtyfQ0KdHdlZXRzIDwtIG1vbmdvKGNvbGxlY3Rpb24gPSAidHdlZXRzX21vbmdvX2NvdmlkMTkiLCBkYiA9ICJETVVCQSIpDQpgYGANCg0KIyMgTm9tYnJlcyBkZSBjb2x1bW5hcw0KYGBge3J9DQpuYW1lcyh0d2VldHMkZmluZCgpKQ0KYGBgDQoNCiMgVGlwb3MgZGUgdHdlZXRzDQpgYGB7cn0NCnQgPC0gbW9uZ28oZGI9IkRNVUJBIiwgY29sbGVjdGlvbj0idHdlZXRfdHlwZSIpDQp0d2VldHNfdHlwZXMgPC0gdCRmaW5kKCkNCmBgYA0KDQpgYGB7cn0NCmNhdCgiQ2FudGlkYWRlcyBkZSB0d2VldHMgcG9yIHRpcG8gXG5cbiIpDQpjYXQoIlx0KiBUd2VldHM6ICIsIG5yb3codHdlZXRzX3R5cGVzKSwgIlxuIikNCmNhdCgiXHQqIFNvbG8gUlQ6ICIsIG5yb3codHdlZXRzX3R5cGVzW3R3ZWV0c190eXBlcyRpc19yZXR3ZWV0ICYgIXR3ZWV0c190eXBlcyRpc19xdW90ZSxdKSwgIlxuIikNCmNhdCgiXHQqIFNvbG8gUVQ6ICIsIG5yb3codHdlZXRzX3R5cGVzWyF0d2VldHNfdHlwZXMkaXNfcmV0d2VldCAmIHR3ZWV0c190eXBlcyRpc19xdW90ZSxdKSwgIlxuIikNCmNhdCgiXHQqIFJUIHkgUVQ6ICIsIG5yb3codHdlZXRzX3R5cGVzW3R3ZWV0c190eXBlcyRpc19yZXR3ZWV0ICYgdHdlZXRzX3R5cGVzJGlzX3F1b3RlLF0pLCAiXG4iKQ0KY2F0KCJcdCogVFcgb3JpZ2luYWxlczogIiwgbnJvdyh0d2VldHNfdHlwZXNbIXR3ZWV0c190eXBlcyRpc19yZXR3ZWV0ICYgIXR3ZWV0c190eXBlcyRpc19xdW90ZSxdKSwgIlxuIikNCg0KYGBgDQoNCmBgYHtyfQ0KdHdlZXRzX3R5cGVzJHRpcG8gPC0gIiINCnR3ZWV0c190eXBlc1t0d2VldHNfdHlwZXMkaXNfcmV0d2VldCAmICF0d2VldHNfdHlwZXMkaXNfcXVvdGUsXSR0aXBvIDwtICJTb2xvIFJUIg0KdHdlZXRzX3R5cGVzWyF0d2VldHNfdHlwZXMkaXNfcmV0d2VldCAmIHR3ZWV0c190eXBlcyRpc19xdW90ZSxdJHRpcG8gPC0gIlNvbG8gUVQiDQp0d2VldHNfdHlwZXNbdHdlZXRzX3R5cGVzJGlzX3JldHdlZXQgJiB0d2VldHNfdHlwZXMkaXNfcXVvdGUsXSR0aXBvIDwtICJSUSB5IFJUIg0KdHdlZXRzX3R5cGVzWyF0d2VldHNfdHlwZXMkaXNfcmV0d2VldCAmICF0d2VldHNfdHlwZXMkaXNfcXVvdGUsXSR0aXBvIDwtICJPcmlnaW5hbCINCmBgYA0KDQoNCmBgYHtyfQ0KIyBuYW1lcyA9IGMoJ1NvbG8gUlQnLCAnU29sbyBRVCcsICdSVCArIFFUJywgJ09yaWdpbmFsJykNCiMgY2FudGlkYWRlcyA9IGMobnJvdyh0d2VldHNfdHlwZXNbdHdlZXRzX3R5cGVzJGlzX3JldHdlZXQgJiAhdHdlZXRzX3R5cGVzJGlzX3F1b3RlLF0pLA0KIyAgICAgICAgICAgICAgICBucm93KHR3ZWV0c190eXBlc1shdHdlZXRzX3R5cGVzJGlzX3JldHdlZXQgJiB0d2VldHNfdHlwZXMkaXNfcXVvdGUsXSksDQojICAgICAgICAgICAgICAgIG5yb3codHdlZXRzX3R5cGVzW3R3ZWV0c190eXBlcyRpc19yZXR3ZWV0ICYgdHdlZXRzX3R5cGVzJGlzX3F1b3RlLF0pLA0KIyAgICAgICAgICAgICAgICBucm93KHR3ZWV0c190eXBlc1shdHdlZXRzX3R5cGVzJGlzX3JldHdlZXQgJiAhdHdlZXRzX3R5cGVzJGlzX3F1b3RlLF0pDQojICAgICAgICAgICAgICAgKQ0KIyAgICAgICAgICAgICAgICANCmdyYWZpY29fdGlwb3MgPC0gZGF0YS5mcmFtZSh0YWJsZSh0d2VldHNfdHlwZXMkdGlwbykpDQoNCiMgYmFycGxvdChzb3J0KGdyYWZpY29fdGlwb3MkRnJlcSwgZGVjcmVhc2luZz1UUlVFKSwgbGVnZW5kLnRleHQ9Z3JhZmljb190aXBvcyRWYXIxLCBjb2w9YygncmVkJywnZ3JlZW4nLCdibHVlJywnYnJvd24nKSkNCiMgYmFycGxvdChoZWlnaHQ9c29ydChncmFmaWNvX3RpcG9zJEZyZXEsIGRlY3JlYXNpbmc9VFJVRSksIG5hbWVzPWdyYWZpY29fdGlwb3MkVmFyMSwgY29sPXJnYigwLjIsMC40LDAuNiwwLjYpICkNCg0KbmFtZXMoZ3JhZmljb190aXBvcykgPC0gYygiVGlwb3MiLCAiQ2FudGlkYWQiKQ0KDQpjb3VsIDwtIGJyZXdlci5wYWwoNSwgIlNldDIiKSANCmJhcnBsb3QoaGVpZ2h0PXNvcnQoZ3JhZmljb190aXBvcyRDYW50aWRhZCwgZGVjcmVhc2luZz1UUlVFKSwgbmFtZXM9Z3JhZmljb190aXBvcyRUaXBvcywgY29sPWNvdWwgKQ0KDQpgYGANCmBgYHtyfQ0KDQojIGNvdWwgPC0gYnJld2VyLnBhbCg1LCAiU2V0MiIpIA0KDQojIHBuZyhmaWxlbmFtZT0idGlwb190d2VldC5wbmciLCB3aWR0aD0xMDAwLCBiZz0id2hpdGUiKQ0KZ2dwbG90KGdyYWZpY29fdGlwb3MsIGFlcyh4PXJlb3JkZXIoVGlwb3MsIENhbnRpZGFkKSwgeT1DYW50aWRhZCwgZmlsbD1UaXBvcykpICsgDQogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArDQogICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iU2V0MiIpICsNCiAgICBsYWJzKA0KICAgICAgdGl0bGUgPSAiIiwNCiAgICAgIHN1YnRpdGxlID0gIiIsDQogICAgICBjYXB0aW9uID0gIiIsDQogICAgICB0YWcgPSAiIg0KICAgICAgKSArDQogICAgeGxhYigiIikgKw0KICAgIHlsYWIoIiIpICsNCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgDQogICAgICAgICAgYXhpcy50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dCggbWFyZ2luID0gbWFyZ2luKDEwLCAxMCwgMTAsIDEwKSksDQogICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbih0ID0gMTAsIHIgPSAxMCwgYiA9IDEwLCBsID0gMTApKSwNCiAgICAgICAgICBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMikpICsNCiAgICBjb29yZF9mbGlwKCkNCiMgZGV2Lm9mZigpDQpgYGANCg0KIyMjICUgZGUgVmVyaWZpY2Fkb3Mgc2Vnw7puIHRpcG8gZGUgdHdlZXQNCmBgYHtyfQ0KDQp0d2VldHMgPC0gbW9uZ28oZGI9IkRNVUJBIiwgY29sbGVjdGlvbj0idHdlZXRfY29tcGxldG9fZXN0YWRpc3RpY2FzIikNCm51bWVyaWNvcyA8LSB0d2VldHMkZmluZCgpDQoNCiMgVGlwb3MNCm51bWVyaWNvcyRUaXBvIDwtICIiDQpudW1lcmljb3NbbnVtZXJpY29zJGlzX3JldHdlZXQgJiAhbnVtZXJpY29zJGlzX3F1b3RlLF0kVGlwbyA8LSAiU29sbyBSVCINCm51bWVyaWNvc1shbnVtZXJpY29zJGlzX3JldHdlZXQgJiBudW1lcmljb3MkaXNfcXVvdGUsXSRUaXBvIDwtICJTb2xvIFFUIg0KbnVtZXJpY29zW251bWVyaWNvcyRpc19yZXR3ZWV0ICYgbnVtZXJpY29zJGlzX3F1b3RlLF0kVGlwbyA8LSAiUVQgeSBSVCINCm51bWVyaWNvc1shbnVtZXJpY29zJGlzX3JldHdlZXQgJiAhbnVtZXJpY29zJGlzX3F1b3RlLF0kVGlwbyA8LSAiT3JpZ2luYWwiDQoNCm51bWVyaWNvcyR2ZXJpZmljYWRvIDwtIEYNCm51bWVyaWNvc1tudW1lcmljb3MkVGlwbyA9PSAiU29sbyBRVCIsXSR2ZXJpZmljYWRvIDwtICBudW1lcmljb3NbbnVtZXJpY29zJFRpcG8gPT0gIlNvbG8gUVQiLF0kcXVvdGVkX3ZlcmlmaWVkDQpudW1lcmljb3NbbnVtZXJpY29zJFRpcG8gPT0gIk9yaWdpbmFsIixdJHZlcmlmaWNhZG8gPC0gIG51bWVyaWNvc1tudW1lcmljb3MkVGlwbyA9PSAiT3JpZ2luYWwiLF0kdmVyaWZpZWQNCm51bWVyaWNvc1tudW1lcmljb3MkVGlwbyA9PSAiU29sbyBSVCIsXSR2ZXJpZmljYWRvIDwtICBudW1lcmljb3NbbnVtZXJpY29zJFRpcG8gPT0gIlNvbG8gUlQiLF0kcmV0d2VldF92ZXJpZmllZA0KbnVtZXJpY29zW251bWVyaWNvcyRUaXBvID09ICJRVCB5IFJUIixdJHZlcmlmaWNhZG8gPC0gIG51bWVyaWNvc1tudW1lcmljb3MkVGlwbyA9PSAiUVQgeSBSVCIsXSRyZXR3ZWV0X3ZlcmlmaWVkDQoNCm51bWVyaWNvcyR2ZXJpZmljYWRvX2dyYWZpY28gPC0gIiINCm51bWVyaWNvc1tudW1lcmljb3MkdmVyaWZpY2FkbyxdJHZlcmlmaWNhZG9fZ3JhZmljbyA8LSAiU2kiDQpudW1lcmljb3NbIW51bWVyaWNvcyR2ZXJpZmljYWRvLF0kdmVyaWZpY2Fkb19ncmFmaWNvIDwtICJObyINCg0KYGBgDQoNCmBgYHtyfQ0KDQojIHBuZyhmaWxlbmFtZT0idGlwb194X3R3ZWV0X2dyaWQyLnBuZyIsIHdpZHRoPTEwMDAsIGJnPSJ3aGl0ZSIpDQpnZ3Bsb3QoZGF0YT1udW1lcmljb3MsIGFlcyh4PXZlcmlmaWNhZG9fZ3JhZmljbywgZmlsbD1UaXBvKSkgKyANCiAgICAgICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iU2V0MiIpICsNCiAgICAgICAgZ2VvbV9iYXIoKSArDQogICAgICAgIGxhYnMoDQogICAgICAgICAgdGl0bGUgPSAiIiwNCiAgICAgICAgICBzdWJ0aXRsZSA9ICIiLA0KICAgICAgICAgIGNhcHRpb24gPSAiIiwNCiAgICAgICAgICB0YWcgPSAiIg0KICAgICAgICAgICkgKw0KICAgICAgICB4bGFiKCIiKSArDQogICAgICAgIHlsYWIoIiIpICsNCiAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIA0KICAgICAgICAgICAgICBheGlzLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dCggbWFyZ2luID0gbWFyZ2luKDEwLCAxMCwgMTAsIDEwKSksDQogICAgICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4odCA9IDEwLCByID0gMTAsIGIgPSAxMCwgbCA9IDEwKSksDQogICAgICAgICAgICAgIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEwKSwNCiAgICAgICAgICAgICAgYXNwZWN0LnJhdGlvPTE5LzE5KSArDQogICAgICAgIGZhY2V0X3dyYXAofiBUaXBvLCBucm93PTIpDQojIGRldi5vZmYoKQ0KYGBgDQoNCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YT10d2VldHNfdHlwZXMsIGFlcyh4PXZlcmlmaWVkLCBmaWxsPXRpcG8pKSArIA0KICBnZW9tX2JhcigpICsgZmFjZXRfd3JhcCh+IHRpcG8sIG5yb3c9MikNCmBgYA0KDQpIYXkgbcOhcyB1c3VhcmlvcyB2ZXJpZmljYWRvcyBlbiBlbCBjb250ZW5pZG8gbnVldm8uIEEgc3UgdmV6LCBoYXkgbcOhcyB2ZXJpZmljb3MgZW4gZWwgY29udGVuaWRvIGNpdGFkby4gRXNvIGhhYmxhIGRlIHF1ZSB1biB1c3VhcmlvIHZlcmlmaWNhZG8gY3JlYSB1biBjb250ZW5pZG8gZGUgbWF5b3IgY2FsaWRhZCAoTcOhcyBkaWZ1bmRpZG8geSBub3ZlZG9zbykuDQoNCk1pZW50cmFzIHF1ZSBlbCB1c3VhcmlvIGRpZnVzb3IgeSBsb3MgcmV0d2VldHMsIHNpIGJpZW4gYXVtZW50YW4gZWwgYWxjYW5jZSBkZSBsb3MgdHdlZXRzLCBubyB0aWVuZW4gdW5hIGNhbGlkYWQgYWx0YS4gDQoNCiMjIFR3ZWV0cyBzZWfDum4gdGllbXBvDQoNCmBgYHtyfQ0KdCA8LSBtb25nbyhkYj0iRE1VQkEiLCBjb2xsZWN0aW9uPSJmZWNoYXMiKQ0KdHdlZXRzX2ZlY2hhcyA8LSB0JGZpbmQoKQ0KYGBgDQoNCmBgYHtyfQ0Kc3VtbWFyeSh0d2VldHNfZmVjaGEpDQpgYGANCg0KDQpFbiB1biBwcmltZXIgaW50ZW50byBkZSBncmFmaWNhciwgdmVtb3MgcXVlIGxvcyBkYXRvcyBlc3RhbiBkaXN0cmlidWlkb3MgZGUgdW5hIGZvcm1hIHBhcnRpY3VsYXIuIExhIHByaW1lcmEgcHJlZ3VudGEgZXMgwr9IYXkgYWxndW5hIGZlY2hhIHF1ZSBwcmVzZW50w7MgdW5hIGNhbnRpZGFkIGFuw7NtYWxhIGRlIGRhdG9zPw0KDQpFbCAyIGRlIG1heW8gbG8gZXMuIFNpbiBlbWJhcmdvLCBubyBmdWUgdW4gZMOtYSBlbiBlbCBxdWUgYWNvbnRlY2nDsyBhbGd1bmEgY29zYS4gTmkgZXMgZmVyaWFkbyAoMS81KSwgbmkgZnVlIGTDrWEgZGUgYW51bmNpb3MgKDI1LzQpLg0KDQpgYGB7cn0NCiMgcGxvdCh0d2VldHNfZmVjaGEkZmVjaGEpDQojIGJhcnBsb3QodGFibGUoYXMuRGF0ZSh0d2VldHNfZmVjaGEkZmVjaGEpKSkNCmY8LSBkYXRhLmZyYW1lKHRhYmxlKGFzLkRhdGUodHdlZXRzX2ZlY2hhJGZlY2hhKSkpDQpnZ3Bsb3QoZGF0YT1mLCBhZXMoeD1GcmVxKSkgKyANCiAgZ2VvbV9oaXN0b2dyYW0oZmlsbD0iIzY5YjNhMiIsIGNvbG9yPSIjZTllY2VmIiwgYWxwaGE9MC45KSArDQogICAgZ2d0aXRsZSgiQmluIHNpemUgPSAzIikgKw0KICAgIHRoZW1lX2lwc3VtKCkgKw0KICAgIHRoZW1lKA0KICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE1KQ0KICAgICkNCmBgYA0KDQpBZ3J1cGFuZG8gZW4gZnJhY2Npb25lcyBtZW5vcywgNSBtaW51dG9zLCB2ZW1vcyBxdWUgbG8gcXVlIGFjb250ZWNpw7MgZnVlIHVuYSB2ZW50YW5hIGRlIGNhcHR1cmEgZGUgZGF0b3MgZGVzaWd1YWwuIEFsIHJlZHVjaXIgbGEgdmVudGFuYSBkZSB0aWVtcG8sIHZlbW9zIHF1ZSBoYXkgdW5hIGRpc3RyaWJ1Y2nDs24gbcOhcyB1bmlmb3JtZS4gSWd1YWxtZW50ZSBzaWd1ZSBwbGFudGVhbmRvc2UgbGEgcHJlZ3VudGEsIHBvZHLDrWFtb3MgYW5hbGl6YXJsbyBkZSBhIG1pbnV0b3MsIG8gY29uIGRpZmVyZW5jaWFzIHBvcmNlbnR1YWxlcywgcGFyYSB2ZXIgc2kgcmVhbG1lbnRlIGh5YSBhbGdvIGFow60uDQoNCmBgYHtyfQ0KdHdlZXRzX2ZlY2hhJHQgPC0geW1kX2htcyh0d2VldHNfZmVjaGEkZmVjaGEpDQp0d2VldHNfZmVjaGEkdGMgPC0gY3V0KHR3ZWV0c19mZWNoYSR0LCBicmVha3MgPSAiNSBtaW4iKSAgDQpjYW50XzVfbWluIDwtIGNvdW50KHR3ZWV0c19mZWNoYSwgdGMpDQpiYXJwbG90KGNhbnRfNV9taW4kbiwgbGVnZW5kLnRleHQ9Y2FudF81X21pbiR0YykNCiMjIFR3ZWV0cyBwb3IgZmVjaGENCnR3ZWV0c19mZWNoYSR0IDwtIHltZF9obXModHdlZXRzX2ZlY2hhJGZlY2hhKQ0KDQojIFBvciBtaW51dG8gZXN0w6EgbcOhcyBlcXVpbGlicmFkbykNCnR3ZWV0c19mZWNoYSR0YyA8LSBjdXQodHdlZXRzX2ZlY2hhJHQsIGJyZWFrcyA9ICIxIG1pbiIpICANCmNhbnRfNV9taW4gPC0gY291bnQodHdlZXRzX2ZlY2hhLCB0YykNCmJhcnBsb3QoY2FudF81X21pbiRuKQ0KYGBgDQpMYSB2YXJpYWJsZSB0ZW1wb3JhbCBwYXJlY2Ugc2VyIGFyYml0cmFyaWEuIA0KDQpBbGdvIGEgc2VndWlyIGludmVzdGlnYW5kbyBlcyBsYSB2ZW50YW5hIHRlbXBvcmFsIGVudHJlOg0KICAqIEZlY2hhIGNyZWFkYSB5IGZlY2hhIGRlIGNyZWFjaW9uIGRlbCByZXR3ZWV0DQogICogRmVjaGEgY3JlYWRhIHkgZmVjaGEgZGUgY3JlYWNpb24gZGVsIHF1b3RlZA0KICANCiAgDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KCJwbG90bHkiKQ0KbGlicmFyeShocmJydGhlbWVzKQ0KIyB0d2VldHNfZmVjaGEkZmVjaGENCnR3ZWV0c19mZWNoYSRmZWNoYV9zdHIgPC0gIGxhcHBseSh0d2VldHNfZmVjaGEkdGMsIGFzLmNoYXJhY3RlcikNCmIgPC0gYXMuUE9TSVhsdChzdHJwdGltZSh0d2VldHNfZmVjaGEkdGMsIGZvcm1hdCA9ICIlSDolTTolUyIpKQ0KY2FudF81X21pbiRmZWNoYSA8LSBhcy5EYXRlKGNhbnRfNV9taW4kdGMpDQpjYW50XzVfbWluJGhvcmEgPC0gIGZvcm1hdChzdHJwdGltZShjYW50XzVfbWluJHRjLCBmb3JtYXQgPSAiJVktJW0tJWQgJUg6JU06JVMiKSwgZm9ybWF0PSIlSDolTTolUyIpDQoNCnAgPC0gY2FudF81X21pbiAlPiUNCiAgZ2dwbG90KCBhZXMoeD1yZW9yZGVyKGhvcmEsIGhvcmEpLCB5PW4sIGZpbGw9bikpICsgDQogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArDQogICAgc2NhbGVfZmlsbF9ncmFkaWVudDIobG93PSdyZWQnLCBtaWQ9J3Nub3czJywgaGlnaD0nZGFya2dyZWVuJywgc3BhY2U9J0xhYicpICsNCiAgICAgICAgbGFicygNCiAgICAgICAgICB0aXRsZSA9ICIiLA0KICAgICAgICAgIHN1YnRpdGxlID0gIiIsDQogICAgICAgICAgY2FwdGlvbiA9ICIiLA0KICAgICAgICAgIHRhZyA9ICIiDQogICAgICAgICAgKSArDQogICAgICAgIHhsYWIoIiIpICsNCiAgICAgICAgeWxhYigiIikgKw0KICAgIHRoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50aWNrcy54PWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50aXRsZS55PWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpKSArDQogICAgZmFjZXRfd3JhcCh+IGZlY2hhLCBucm93PTQpDQoNCnBuZyhmaWxlbmFtZT0idGlwb194X3R3ZWV0LnBuZyIsIHdpZHRoPTEwMDAsIGJnPSJ3aGl0ZSIpDQpwDQpkZXYub2ZmKCkNCg0KIyBUdXJuIGl0IGludGVyYWN0aXZlIHdpdGggZ2dwbG90bHkNCnAgPC0gZ2dwbG90bHkocCkNCnANCmBgYA0KDQoNCiMjIFRleHRvDQoNCmBgYHtyfQ0KdHdlZXRzX3RleHQgPC0gdHdlZXRzJGFnZ3JlZ2F0ZSgnW3sNCiAgICAgICAgICAgICIkcHJvamVjdCI6IHsgDQogICAgICAgICAgICAgICAgIl9pZCI6ICIkX2lkIiwNCiAgICAgICAgICAgICAgICAidGV4dCI6ICIkdGV4dCINCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgIF0nKQ0KIyBzdW1tYXJ5KHR3ZWV0c190ZXh0KQ0KIyAjIHR3ZWV0c190ZXh0JGNhbnRDaGFycyA8LSBuY2hhcih0d2VldHNfdGV4dCR0ZXh0KQ0KIyBzdW1tYXJ5KHR3ZWV0c190ZXh0KQ0KIyBQb3IgaGF5IHVuIHR3ZWV0IGRlIDkwMCBjaGFyPyBzZXLDoSBwb3IgdXJsIG8gY29zYXMgYXPDrT8NCmJveHBsb3QodHdlZXRzX3RleHQkY2FudENoYXJzKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KHR3ZWV0c190ZXh0LCBhZXMoeD1jYW50Q2hhcnMpKSArDQogIGdlb21fZGVuc2l0eShmaWxsPSIjNjliM2EyIiwgY29sb3I9IiNlOWVjZWYiLCBhbHBoYT0wLjgpICsNCiAgZ2d0aXRsZSgiQ2FudGlkYWQgZGUgY2F0YWN0ZXJlcyBwb3IgdHdlZXQiKSArDQogIHRoZW1lX2lwc3VtKCkNCmBgYA0KIyMjIE1lbm9zIHVzZXIgeSBsaW5rcyByZWZlcmVuY2VzDQoNCmBgYHtyfQ0KdHdlZXRzX3RleHQuZGYyIDwtIHR3ZWV0c190ZXh0DQp0d2VldHNfdGV4dC5kZjIkdGV4dCA8LSBnc3ViKCJodHRwLioiLCIiLHR3ZWV0c190ZXh0LmRmMiR0ZXh0KQ0KdHdlZXRzX3RleHQuZGYyJHRleHQgPC0gZ3N1YigiaHR0cHMuKiIsIiIsdHdlZXRzX3RleHQuZGYyJHRleHQpDQoNCiNRdWl0YW5kbyBsb3MgaGFzaHRhZ3MgeSB1c3VhcmlvcyBlbiBsb3MgdHdlZXRzX3RleHQNCnR3ZWV0c190ZXh0LmRmMiR0ZXh0IDwtIGdzdWIoIiNcXHcrIiwiIix0d2VldHNfdGV4dC5kZjIkdGV4dCkNCnR3ZWV0c190ZXh0LmRmMiR0ZXh0IDwtIGdzdWIoIkBcXHcrIiwiIix0d2VldHNfdGV4dC5kZjIkdGV4dCkNCg0KdHdlZXRzX3RleHQuZGYyJGNhbnRDaGFycyA8LSBuY2hhcih0d2VldHNfdGV4dC5kZjIkdGV4dCkNCmdncGxvdCh0d2VldHNfdGV4dC5kZjIsIGFlcyh4PWNhbnRDaGFycykpICsNCiAgZ2VvbV9kZW5zaXR5KGZpbGw9IiM2OWIzYTIiLCBjb2xvcj0iI2U5ZWNlZiIsIGFscGhhPTAuOCkgKw0KICBnZ3RpdGxlKCJDYW50aWRhZCBkZSBjYXRhY3RlcmVzIHBvciB0d2VldCIpICsNCiAgdGhlbWVfaXBzdW0oKQ0KYGBgDQoNCiMjIyBNZW5vcyBudW1lcm9zIHkgc2ltYm9sb3MNCg0KYGBge3J9DQoNCnR3ZWV0c190ZXh0LmRmMiR0ZXh0IDwtIGdzdWIoIltbOnB1bmN0Ol1dIiwiIix0d2VldHNfdGV4dC5kZjIkdGV4dCkNCnR3ZWV0c190ZXh0LmRmMiR0ZXh0IDwtIGdzdWIoIlxcdypbMC05XStcXHcqXFxzKiIsICIiLHR3ZWV0c190ZXh0LmRmMiR0ZXh0KQ0KdHdlZXRzX3RleHQuZGYyJGNhbnRDaGFycyA8LSBuY2hhcih0d2VldHNfdGV4dC5kZjIkdGV4dCkNCmdncGxvdCh0d2VldHNfdGV4dC5kZjIsIGFlcyh4PWNhbnRDaGFycykpICsNCiAgZ2VvbV9kZW5zaXR5KGZpbGw9IiM2OWIzYTIiLCBjb2xvcj0iI2U5ZWNlZiIsIGFscGhhPTAuOCkgKw0KICBnZ3RpdGxlKCJTaW4gY2FyYWN0ZXJlcyBlc3BlY2lhbGVzIHkgbnVtZXJvcyIpICsNCiAgdGhlbWVfaXBzdW0oKQ0KDQpgYGANCg0KIyBIYXNodGFncw0KDQojIyBDYW50aWRhZCBkZSBudWxvcw0KYGBge3J9DQp0d2VldHNfaGFzaGVzX251bGwgPC0gdHdlZXRzJGZpbmQoJ3siaGFzaHRhZ3MiOnsiJGVsZW1NYXRjaCI6eyIkaW4iOltudWxsXSwgIiRleGlzdHMiOnRydWV9fX0nKQ0KcHJpbnQobnJvdyh0d2VldHNfaGFzaGVzKSkNCmBgYA0KDQojIyBQcmVwcm9jZXNhbWllbnRvDQpgYGB7cn0NCnR3ZWV0c19jb3VudCA8LSBtb25nbyhkYj0nRE1VQkEnLCBjb2xsZWN0aW9uPSd0d2VldF9jb3VudF9oYXNodGFncycpDQp0d2VldHNfY291bnQgPC0gdHdlZXRzX2NvdW50JGZpbmQoKQ0KdHdlZXRzX2NvdW50JGhhc2h0YWdfMiA8LSBnc3ViKCJbWzpwdW5jdDpdXSIsIiIsdHdlZXRzX2NvdW50JGhhc2h0YWcpOw0KdHdlZXRzX2NvdW50JGhhc2h0YWdfMiA8LSBnc3ViKCJbXls6YWxudW06XVs6Ymxhbms6XT8mL1xcLV0iLCAiIiwgdHdlZXRzX2NvdW50JGhhc2h0YWdfMik7DQp0d2VldHNfY291bnQkaGFzaHRhZ18yIDwtIGljb252KHR3ZWV0c19jb3VudCRoYXNodGFnXzIsZnJvbT0iVVRGLTgiLHRvPSJBU0NJSS8vVFJBTlNMSVQiKTsNCnR3ZWV0c19jb3VudCRpc19jdWFyZW50ZW5hX3JlbGF0ZWQgPC0gRg0KZm9yIChpIGluIGN1YXJlbnRlbmFfd29yZHMpIHsNCiAgdHdlZXRzX2NvdW50JGlzX2N1YXJlbnRlbmFfcmVsYXRlZCA8LSBpZmVsc2UoZ3JlcGwoaSwgdHdlZXRzX2NvdW50JGhhc2h0YWdfMiwgZml4ZWQ9IFQpLCBULCB0d2VldHNfY291bnQkaXNfY3VhcmVudGVuYV9yZWxhdGVkKQ0KfQ0KdHdlZXRzX2NvdW50JGlzX3NleF9yZWxhdGVkIDwtIEYNCmZvciAoaSBpbiBzZXhfd29yZHMpIHsNCiAgdHdlZXRzX2NvdW50JGlzX3NleF9yZWxhdGVkIDwtIGlmZWxzZShncmVwbChpLCB0d2VldHNfY291bnQkaGFzaHRhZ18yLCBmaXhlZD0gVCksIFQsIHR3ZWV0c19jb3VudCRpc19zZXhfcmVsYXRlZCkNCn0NCmBgYA0KDQpUb3AgMjAgZGUgaGFzaHRhZ3Mgbm8gcmVsYWNpb25hZG9zIGEgY3VhcmVudGVuYQ0KYGBge3J9DQpoZWFkKHR3ZWV0c19jb3VudFshdHdlZXRzX2NvdW50JGlzX2N1YXJlbnRlbmFfcmVsYXRlZCAmICF0d2VldHNfY291bnQkaXNfc2V4X3JlbGF0ZWQsXSAlPiUgc2VsZWN0KDI6MyksIG49MjApDQoNCmBgYA0KDQoNCkFsZ28gcXVlIG1lIGxsYW1vIGxhIGF0ZW5jaW9uOiANCiogQ3ViYQ0KKiBNw6l4aWNvLCBiYXJ0bGV0dCAoTWluaXN0cm8gbWV4aWNhbm8pLCBzbnRlIChzaW5kaWNhdG8gZGUgcHJvZmVzb3JlcykuDQoqIFZlbmV6dWVsYSwgcHJvdGVjY2lvbnlhY2Npb24NCiogQUZQLCB0ZW7DrWEgdW5hIGRvYmxlIGltcGxpY2FjacOzbiBmb25kbyBkZSBwZW5zacOzbiBvIGFnZW5jaWEgZGUgcHJlbnNhIGZyYW5jZXNhLiBMYSBwcmltZXJhIGlkZWEgZGUgdW4gZm9uZG8gZGUgcGVuc2lvbmVzIHF1ZSBwdWRpZXNlIHVzYXJzZSBjb21vIGZvbmRvIGRlIGVtZXJnZW5jaWEgeSBxdWUgZ2VuZXJhYmEgcG9sw6ltaWNhIGVyYSBpbnRlcmVzYW50ZSBjb21vIHJlYWNjaW9uIGFsIGNvdmlkLiBTaW4gZW1iYXJnbyBoYWNpZW5kbyB1bmEgc2VndW5kYSBiw7pzcXVlZGEgYXBhcnRpciBkZWwgY2FtcG8gdGV4dG8sIHZlbW9zIHF1ZSB1biBoYXNodGFnIGNvbiByZXBlcmN1c2nDs24gYW1iaWd1YSwgdG9jYSBhbWJvcyB0ZW1hcyB5IGFkZW3DoXMgZm9uZG9zIGRlIHBlbnNpw7NuIGRlIG90cm9zIHBhw61zZXMuIFBvciBsbyBxdWUgZW50cmFyIGVuIGVsIHNpZ25pZmljYSBtdWNobyB0aWVtcG8geSBwb2NhIGluZm9ybWFjacOzbiBlc3BlY8OtZmljYS4gDQoNCg0KVE9ETzogDQoqIEhheSBhbGdvIGNvbiBwb3NpYmlsaWRhZCBkZSBzZXIgcHJvZnVuZGl6YWRvLCBxdWUgZXMgcG9ycXVlIGRlIGNhZGEgdW5vLCBxdWUgaW1wYWN0bywgcXVpZW5lcyBsbyBnZW5lcmFyb24sIHF1ZSBpbmZsdWVuY2lhLCBmdWVyb24gdHJlbmRpbmcgdG9waWMsIGN1YW50b3MgZMOtYXM/IA0KKiBBcmdlbnRpbmEgdnMgZWwgcmVzdG8gKEN1YmEsIE1leGljbywgQ2hpbGUpLg0KKiBUaWVuZW4gcXVlIHZlciBlc3RvcyBoYXNodGFncyBjb24gbG9zIHRyZW5kaW5nIHRvcGljPyBtaXNtbyBzaWVuZG8gcmFuZG9tLCBsbGVnYW1vcyBhIG9idGVuZXIgcGFydGUgZGUgZXNhIHJlcHJlc2VudGF0aXZpZGFkIGRlIGxvcyB0cmVuZGluZyB0b3BpY3M/DQoNCiMgUGVyZmlscyBkZSBVc3VhcmlvczoNCg0KYGBge3J9DQp1c2VyX2VzdGFkaXN0aWNhcyA8LSBtb25nbyhkYj0iRE1VQkEiLCBjb2xsZWN0aW9uPSJ1c2VyX2VzdGFkaXN0aWNhcyIpDQpzdW1tYXJ5KGluZm9fdXNlcikNCiMgVXNlciBiYXNlDQppbmZvX3VzZXIgPC0gdXNlcl9lc3RhZGlzdGljYXMkZmluZCgpDQojIENvbiBsb2cgc2luIGxvcyBxdWUgdGllbmUgMA0KZGF0YV9sb2cgPC0gYXMuZGF0YS5mcmFtZShhcHBseShpbmZvX3VzZXJbLDU6OV0sIDIsIGxvZykpDQojIExvZyBjb24gbG9zIHF1ZSB0aWVuZSAwDQppbmZvX3VzZXJbaW5mb191c2VyID09IDBdIDwtIDAuMDAwMDENCmRhdGFfbG9nXzEgPC0gYXMuZGF0YS5mcmFtZShhcHBseShpbmZvX3VzZXJbLDU6OV0sIDIsIGxvZykpDQoNCmNhdCgiQ2FudGlkYWQgZGUgdXN1YXJpb3MgcXVlIGhhbiB0d2l0dGVhZG86ICIsIG5yb3coaW5mb191c2VyKSkNCmBgYA0KDQpgYGB7cn0NCg0KIyBnZ3BhaXJzKGRhdGFfbG9nKQ0KIyBnZ3BhaXJzKGluZm9fdXNlclssMTo1XSkNCg0KYm94cGxvdChpbmZvX3VzZXJbLDU6OV0pDQoNCiMgQ29uIDAncw0KYm94cGxvdChkYXRhX2xvZykNCiMgQ29uIDAuMDAwMDAwMSdzDQpib3hwbG90KGRhdGFfbG9nXzEpDQoNCiMgDQojIGluZm9fdXNlciR2ZXJpZmljYWRvIDwtIGlmZWxzZShpbmZvX3VzZXIkdmVyaWZpZWQsICJWZXJpZmljYWRvcyIsICJTaW4gdmVyaWZpY2FyIikNCiMgaW5mb191c2VyJHZlcmlmaWNhZG8gPC0gYXMuZmFjdG9yKGluZm9fdXNlciR2ZXJpZmljYWRvKQ0KDQpgYGANCg0KVG9kbzogDQoqIEp1bnRhciB1c3VhcmlvcyBmaW5hbGVzLCB1c3VhcmlvcyBxdWUgZnVlcm9uIHJlcGxpY2Fkb3MNCiogUXVlIGhhY2UgcXVlIHVuIHVzdWFyaW8gc2VhIG3DoXMgZGl2dWxnYWRvPyBIYXkgYWxndW5hIG1lZGlkYSBkZSByZWxldmFuY2lhIGRlIHVuIHVzdWFyaW8/IEFxdWVsbG9zIG3DoXMgcG9wdWxhcmVzIChTZWd1biBxdWUgY3JpdGVyaW8/KSBzb24gZGUgcXVlIHRpcG8/IEluc3RpdHVjaW9uZXMsIHVzdWFyaW9zIGNvbXVuZXMsIGJvdHM/IFF1ZSB0YW4gYWN0aXZvcyBzb24/IEluZmx1eWUgZXNvPyBEZXNkZSBxdWUgZGlzcG9zaXRpdm8gbG8gaGFjZW4/IFF1ZSB0aXBvIGRlIHRleHRvIGNyZWFuPyBRdWUgaGFzaHRhZ3MgdXNhbj8gDQpEZSBxdWUgcmVnaW9uZXMgc29uPyBIYXkgYWxnbyBpbnRlcmVzYW50ZSBhaMOtPyBIYXkgcHJlZG9taW5pbyBkZSBhbGd1biBwYWlzPyBIYXkgcGFpc2VzIGRvbmRlIHNlIHVzYSBtw6FzIGVsIHR3aXR0ZXI/IA0KDQoNCiMgVGlwb3MgZGUgdXN1YXJpb3M6DQoNCmBgYHtyfQ0KDQp1c2VyX3R3ZWV0c19lc3RhZGlzdGljYXMgPC0gbW9uZ28oZGI9IkRNVUJBIiwgY29sbGVjdGlvbj0idXNlcl90d2VldHNfZXN0YWRpc3RpY2FzIikNCiMgVXNlciBiYXNlDQppbmZvX3VzZXIgPC0gdXNlcl90d2VldHNfZXN0YWRpc3RpY2FzJGZpbmQoKQ0Kc3VtbWFyeShpbmZvX3VzZXIkaXNfbm9uZSkNCg0KDQppbmZvX3VzZXJbaW5mb191c2VyID09IDBdIDwtIDAuMDAwMDENCmRhdGFfbG9nXzEgPC0gYXMuZGF0YS5mcmFtZShhcHBseShpbmZvX3VzZXJbLDM6N10sIDIsIGxvZykpDQojIFBsb3QgZGUgZ3J1cG9zDQoNCnBsb3Qoc29ydChkYXRhX2xvZ18xJGlzX3J0KSkNCnBsb3Qoc29ydChkYXRhX2xvZ18xJGlzX29ubHlfcnQpKQ0KcGxvdChzb3J0KGRhdGFfbG9nXzEkaXNfb25seV9xdCkpDQpwbG90KHNvcnQoZGF0YV9sb2dfMSRpc19ub25lKSkNCnBsb3Qoc29ydChkYXRhX2xvZ18xJGlzX3F0KSkNCg0KYGBgDQoNClRPRE86IEJpbm5pbmcgY29uIGVzdG8/IEFsaW5lYXIgZGlzdGludG9zIGdydXBvcyBlbiBjYWRhIGNhdGVnb3JpYT8gU29sbyBjbGFzaWZpY2FybG9zPw0KDQoNCiMjIFVzdWFyaW9zIGNvbiBtw6FzIHR3ZWV0cw0KDQpgYGB7cn0NCmhlYWQoaW5mb191c2VyW29yZGVyKGluZm9fdXNlciRjb3VudCwgZGVjcmVhc2luZyA9IFQpLF0pDQpgYGANCg0KQ3VyaW9zYW1lbnRlLCBsb3MgdXN1YXJpb3MgZmluYWxlcyBjb24gbcOhcyB0d2VldHMgc29uIGNyZWFkb3Jlcy4gc2Vyw6FuIGJvdHM/DQoNCiMjIENhdGVnb3JpemFyDQoNCmBgYHtyfQ0KaW5mb191c2VyJHRpcG8gPC0gaWZlbHNlKGluZm9fdXNlciRpc19ub25lID4gaW5mb191c2VyJGlzX29ubHlfcnQgKyBpbmZvX3VzZXIkaXNfb25seV9ydCwgIkNyZWFkb3IiLCAiRGlmdXNvciIpDQpgYGANCg0KYGBge3J9DQpiYXJwbG90KHRhYmxlKGluZm9fdXNlciR0aXBvKSkNCmluZm9fdXNlcl9ncmFmIDwtIGRhdGEuZnJhbWUodGFibGUoaW5mb191c2VyJHRpcG8pKQ0KbmFtZXMoaW5mb191c2VyX2dyYWYpIDwtIGMoIlRpcG9fdXN1YXJpbyIsICJDYW50aWRhZCIpDQoNCiMgcG5nKGZpbGVuYW1lPSJ0aXBvX3VzdWFyaW9fY3JlYWNpb24ucG5nIiwgd2lkdGg9MTAwMCwgYmc9IndoaXRlIikNCmdncGxvdChpbmZvX3VzZXJfZ3JhZiwgYWVzKHg9cmVvcmRlcihUaXBvX3VzdWFyaW8gLCBDYW50aWRhZCksIHk9Q2FudGlkYWQsIGZpbGw9VGlwb191c3VhcmlvKSkgKyANCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsNCiAgICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJTZXQyIikgKw0KICAgIGxhYnMoDQogICAgICB0aXRsZSA9ICIiLA0KICAgICAgc3VidGl0bGUgPSAiIiwNCiAgICAgIGNhcHRpb24gPSAiIiwNCiAgICAgIHRhZyA9ICIiDQogICAgICApICsNCiAgICB4bGFiKCIiKSArDQogICAgeWxhYigiIikgKw0KICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCANCiAgICAgICAgICBheGlzLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTQpLA0KICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KCBtYXJnaW4gPSBtYXJnaW4oMTAsIDEwLCAxMCwgMTApKSwNCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKHQgPSAxMCwgciA9IDEwLCBiID0gMTAsIGwgPSAxMCkpLA0KICAgICAgICAgICAgICBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xNCksDQogICAgIyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgDQogICAgIyAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKHQgPSAxMCwgciA9IDEwLCBiID0gMTAsIGwgPSAxMCkpDQogICAgICAgICAgKSArDQogICAgY29vcmRfZmxpcCgpDQojIGRldi5vZmYoKQ0KYGBgDQoNCiMjIyBVc3VhcmlvcyBzZWfDum4gcG9wdWxhcmlkYWQNCg0KYGBge3J9DQp1c2VyX2VzdGFkaXN0aWNhcyA8LSBtb25nbyhkYj0iRE1VQkEiLCBjb2xsZWN0aW9uPSJ1c2VyX2VzdGFkaXN0aWNhcyIpDQppbmZvX3VzZXIgPC0gdXNlcl9lc3RhZGlzdGljYXMkZmluZCgpDQoNCmRhdGFfbG9nIDwtIGFzLmRhdGEuZnJhbWUoYXBwbHkoaW5mb191c2VyWyw1OjldLCAyLCBsb2cxMCkpDQppbmZvX3VzZXJbaW5mb191c2VyID09IDBdIDwtIDAuMDAwMDENCmluZm9fdXNlcltpcy5uYShpbmZvX3VzZXIpXSA8LSAwLjAwMDENCmRhdGFfbG9nXzEgPC0gYXMuZGF0YS5mcmFtZShhcHBseShpbmZvX3VzZXJbLDU6OV0sIDIsIGxvZzEwKSkNCg0KYGBgDQoNCkNvcnJlbGxhdGlvbnMNCmBgYHtyfQ0KZ2dwYWlycyhkYXRhX2xvZ18xKQ0KYGBgDQoNCg0KYGBge3J9DQoNCmJpbl9lcV9mcmVxIDwtIGRpc2NyZXRpemUoZGF0YV9sb2dfMSRmb2xsb3dlcnNfY291bnQsImVxdWFsZnJlcSIsIDIwKQ0KYmluX2VxX2ZyZXEkZm9sbG93ZXJzX2NvdW50ID0gZGF0YV9sb2dfMSRmb2xsb3dlcnNfY291bnQNCg0KIyBQb3IgY2FkYSBiaW4gY2FsY3VsYW1vcyBsYSBtZWRpYSB5IHJlZW1wbGF6YW1vcyBlbiBlbCBhdHJpYnV0byBzdWF2aXphZG8NCmZvcihiaW4gaW4gMToyMCl7DQogIGJpbl9lcV9mcmVxJHN1YXZpemFkb1sgYmluX2VxX2ZyZXEkWD09YmluXSA9IG1lYW4oYmluX2VxX2ZyZXEkZm9sbG93ZXJzX2NvdW50WyBiaW5fZXFfZnJlcSRYPT1iaW5dKQ0KfQ0KDQojIGdyYWZpY28gU2VwYWwuV2lkdGggb3JkZW5hZG8gZGUgbWVub3IgYSBtYXlvcg0KcGxvdChzb3J0KGRhdGFfbG9nXzEkZm9sbG93ZXJzX2NvdW50KSAsIHR5cGUgPSAicCIsIGNvbD0icmVkIiwgDQogICAgIHlsYWIgPSAiZm9sbG93ZXJzX2NvdW50IiwgeGxhYiA9ICJPYnNlcnZhY2lvbmVzIiwgbWFpbiA9ICJEYXRvIG9yaWdpbmFsIHZzIHN1YXZpemFkbyIpDQojIEFncmVnbyBsYSBzZXJpZSBkZSBsYSB2YXJpYWJsZSBtZWRpYSANCmxpbmVzKHNvcnQoYmluX2VxX2ZyZXEkc3Vhdml6YWRvKSwNCiAgICAgIHR5cGUgPSAicCIsIGNvbD0iYmx1ZSIpDQpsZWdlbmQoInRvcGxlZnQiLCBsZWdlbmQ9YygiT3JpZ2luYWwiLCAiU3Vhdml6YWRvIiksIGNvbD1jKCJyZWQiLCAiYmx1ZSIpLCBsdHk9MSkNCmBgYA0KDQpgYGB7cn0NCg0KDQpiaW5fZXFfZnJlcSA8LSBkaXNjcmV0aXplKGRhdGFfbG9nXzEkbGlzdGVkX2NvdW50LCJlcXVhbGZyZXEiLCAyMCkNCmJpbl9lcV9mcmVxJGxpc3RlZF9jb3VudCA9IGRhdGFfbG9nXzEkbGlzdGVkX2NvdW50DQoNCiMgUG9yIGNhZGEgYmluIGNhbGN1bGFtb3MgbGEgbWVkaWEgeSByZWVtcGxhemFtb3MgZW4gZWwgYXRyaWJ1dG8gc3Vhdml6YWRvDQpmb3IoYmluIGluIDE6MjApew0KICBiaW5fZXFfZnJlcSRzdWF2aXphZG9bIGJpbl9lcV9mcmVxJFg9PWJpbl0gPSBtZWFuKGJpbl9lcV9mcmVxJGxpc3RlZF9jb3VudFsgYmluX2VxX2ZyZXEkWD09YmluXSkNCn0NCg0KIyBncmFmaWNvIFNlcGFsLldpZHRoIG9yZGVuYWRvIGRlIG1lbm9yIGEgbWF5b3INCnBsb3Qoc29ydChkYXRhX2xvZ18xJGxpc3RlZF9jb3VudCkgLCB0eXBlID0gInAiLCBjb2w9InJlZCIsIA0KICAgICB5bGFiID0gImxpc3RlZF9jb3VudCIsIHhsYWIgPSAiT2JzZXJ2YWNpb25lcyIsIG1haW4gPSAiRGF0byBvcmlnaW5hbCB2cyBzdWF2aXphZG8iKQ0KIyBBZ3JlZ28gbGEgc2VyaWUgZGUgbGEgdmFyaWFibGUgbWVkaWEgDQpsaW5lcyhzb3J0KGJpbl9lcV9mcmVxJHN1YXZpemFkbyksDQogICAgICB0eXBlID0gInAiLCBjb2w9ImJsdWUiKQ0KbGVnZW5kKCJ0b3BsZWZ0IiwgbGVnZW5kPWMoIk9yaWdpbmFsIiwgIlN1YXZpemFkbyIpLCBjb2w9YygicmVkIiwgImJsdWUiKSwgbHR5PTEpDQpgYGANCg0KIyMjIFVzdWFyaW9zIHNlZ8O6biBhY3RpdmlkYWQNCg0KYGBge3J9DQojIG5vX25hX2RhdGEgPC0gZGF0YV9sb2dfMVshaXMubmEoZGF0YV9sb2dfMSRzdGF0dXNlc19jb3VudCksXQ0KYmluX2VxX2ZyZXEgPC0gZGlzY3JldGl6ZShkYXRhX2xvZ18xJHN0YXR1c2VzX2NvdW50LCJlcXVhbHdpZHRoIiwgNSkNCmJpbl9lcV9mcmVxJHN0YXR1c2VzX2NvdW50ID0gZGF0YV9sb2dfMSRzdGF0dXNlc19jb3VudA0KDQojIFBvciBjYWRhIGJpbiBjYWxjdWxhbW9zIGxhIG1lZGlhIHkgcmVlbXBsYXphbW9zIGVuIGVsIGF0cmlidXRvIHN1YXZpemFkbw0KZm9yKGJpbiBpbiAxOjUpew0KICBiaW5fZXFfZnJlcSRzdWF2aXphZG9bIGJpbl9lcV9mcmVxJFg9PWJpbl0gPSBtZWFuKGJpbl9lcV9mcmVxJHN0YXR1c2VzX2NvdW50WyBiaW5fZXFfZnJlcSRYPT1iaW5dKQ0KfQ0KDQojIGdyYWZpY28gU2VwYWwuV2lkdGggb3JkZW5hZG8gZGUgbWVub3IgYSBtYXlvcg0KcGxvdChzb3J0KGRhdGFfbG9nXzEkc3RhdHVzZXNfY291bnQpICwgdHlwZSA9ICJwIiwgY29sPSJyZWQiLCANCiAgICAgeWxhYiA9ICJzdGF0dXNlc19jb3VudCIsIHhsYWIgPSAiT2JzZXJ2YWNpb25lcyIsIG1haW4gPSAiRGF0byBvcmlnaW5hbCB2cyBzdWF2aXphZG8iKQ0KIyBBZ3JlZ28gbGEgc2VyaWUgZGUgbGEgdmFyaWFibGUgbWVkaWEgDQpsaW5lcyhzb3J0KGJpbl9lcV9mcmVxJHN1YXZpemFkbyksDQogICAgICB0eXBlID0gInAiLCBjb2w9ImJsdWUiKQ0KbGVnZW5kKCJ0b3BsZWZ0IiwgbGVnZW5kPWMoIk9yaWdpbmFsIiwgIlN1YXZpemFkbyIpLCBjb2w9YygicmVkIiwgImJsdWUiKSwgbHR5PTEpDQpgYGANCg0KYGBge3J9DQoNCiMgbm9fbmFfZGF0YSA8LSBkYXRhX2xvZ18xWyFpcy5uYShkYXRhX2xvZ18xJGZhdm91cml0ZXNfY291bnQpLF0NCmJpbl9lcV9mcmVxIDwtIGRpc2NyZXRpemUoZGF0YV9sb2dfMSRmYXZvdXJpdGVzX2NvdW50LCJlcXVhbHdpZHRoIiwgMTApDQpiaW5fZXFfZnJlcSRmYXZvdXJpdGVzX2NvdW50ID0gZGF0YV9sb2dfMSRmYXZvdXJpdGVzX2NvdW50DQoNCiMgUG9yIGNhZGEgYmluIGNhbGN1bGFtb3MgbGEgbWVkaWEgeSByZWVtcGxhemFtb3MgZW4gZWwgYXRyaWJ1dG8gc3Vhdml6YWRvDQpmb3IoYmluIGluIDE6MTApew0KICBiaW5fZXFfZnJlcSRzdWF2aXphZG9bIGJpbl9lcV9mcmVxJFg9PWJpbl0gPSBtZWFuKGJpbl9lcV9mcmVxJGZhdm91cml0ZXNfY291bnRbIGJpbl9lcV9mcmVxJFg9PWJpbl0pDQp9DQoNCiMgZ3JhZmljbyBTZXBhbC5XaWR0aCBvcmRlbmFkbyBkZSBtZW5vciBhIG1heW9yDQpwbG90KHNvcnQoZGF0YV9sb2dfMSRmYXZvdXJpdGVzX2NvdW50KSAsIHR5cGUgPSAicCIsIGNvbD0icmVkIiwgDQogICAgIHlsYWIgPSAiZmF2b3VyaXRlc19jb3VudCIsIHhsYWIgPSAiT2JzZXJ2YWNpb25lcyIsIG1haW4gPSAiRGF0byBvcmlnaW5hbCB2cyBzdWF2aXphZG8iKQ0KIyBBZ3JlZ28gbGEgc2VyaWUgZGUgbGEgdmFyaWFibGUgbWVkaWEgDQpsaW5lcyhzb3J0KGJpbl9lcV9mcmVxJHN1YXZpemFkbyksDQogICAgICB0eXBlID0gInAiLCBjb2w9ImJsdWUiKQ0KbGVnZW5kKCJ0b3BsZWZ0IiwgbGVnZW5kPWMoIk9yaWdpbmFsIiwgIlN1YXZpemFkbyIpLCBjb2w9YygicmVkIiwgImJsdWUiKSwgbHR5PTEpDQoNCmBgYA0KDQoNCg0KVE9ETzogDQoqIERlbnRybyBkZSBsb3MgY3JlYWRvcmVzLCBhbGd1bm8gZnVlIHJldHdldGVhZG8/IENpdGFkbz8gQ3VhbCBlcyBlbCBpbXBhY3RvIGRlIGxvcyBjcmVhZG9yZXM/DQoqIERlbnRybyBkZSBsb3MgZGlmdXNvcmVzLCBxdWUgaW1wYWN0byB0aWVuZW4/IFF1ZSByZWxldmFuY2lhIHRpZW5lbiBsb3MgY3JlYWRvcmVzIG9yaWdpbmFsZXM/IEN1YW5kbyB0d2VldHMgZnVlcm9uIGFtcGxpZmljYWRvcyBtw6FzIGRlIHVuYSB2ZXogZW4gZWwgZ3J1cG8gZGUgdHdpdHRlcm9zIGZpbmFsZXM/DQoqIEVzIG11eSBzaW1wbGlzdGEgZXN0bz8gRnVuY2lvbmE/IEhheSBkaXNwb3NpdGl2b3MgcHJpdmlsZWdpYWRvcz8gVXNhbiBzb2Z0d2FyZSBwYXJhIHB1YmxpY2FjaW9uZXMgbG9zIGNyZWFkb3Jlcz8gTG9zIGRpZnVzb3Jlcz8NCiogRW50cmUgbG9zIGNyZWFkb3JlcywgaGF5IHZlcmlmaWNhZG9zPyBIYXkgYWxndW5hIGZvcm1hIGRlIGV2YWx1YXIgbGEgY29uZmlhYmlsaWRhZCBvIGxhIHZlcmFjaWRhZCBkZSBsbyBxdWUgZGljZW4/DQoqIEVudHJlIGxvcyBkaWZ1c29yZXMsIGhheSBmYWtlIG5ld3M/IEhheSBkaWZ1c2lvbiBpbmRpc2NyaW1pbmFkYT8gSGF5IHJlbGFjaW9uIGVudHJlIGFsZ3VuIHBhciBkZSB1c3Vhcmlvcz8gSGF5IGFsZ3VuYSBwZXJzb25hIHF1ZSB0aWVuZSBtw6FzIGRpZnVzaW9uIHF1ZSBvdHJhPw0Kcw0KDQoNCiMgUGFpc2VzDQoNCmBgYHtyfQ0KDQp0d2VldHMgPC0gbW9uZ28oY29sbGVjdGlvbiA9ICJ0d2VldHNfbG93ZXIiLCBkYiA9ICJETVVCQSIpDQoNCmRmX2xvY2F0aW9uIDwtIHR3ZWV0cyRhZ2dyZWdhdGUoJ1t7DQogICAgICAgICAgICAiJHByb2plY3QiOiB7IA0KICAgICAgICAgICAgICAgICJfaWQiOiAiJF9pZCIsDQogICAgICAgICAgICAgICAgImxvY2F0aW9uIjogIiRsb2NhdGlvbiIsDQogICAgICAgICAgICAgICAgInJldHdlZXRfbG9jYXRpb24iOiAiJHJldHdlZXRfbG9jYXRpb24iLA0KICAgICAgICAgICAgICAgICJxdW90ZWRfbG9jYXRpb24iOiAiJHF1b3RlZF9sb2NhdGlvbiIsDQogICAgICAgICAgICAgICAgImNvdW50cnlfY29kZSI6ICIkY291bnRyeV9jb2RlIiwNCiAgICAgICAgICAgICAgICAiY291bnRyeSI6ICIkY291bnRyeSIsDQogICAgICAgICAgICAgICAgImxhdCI6ICIkbGF0IiwNCiAgICAgICAgICAgICAgICAibG5nIjogIiRsbmciDQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICBdJykNCmBgYA0KDQpgYGB7cn0NCm5vbWJyZV9sb2NhdGlvbiA8LSBjKCJsb2NhdGlvbiIsICJyZXR3ZWV0IiwgInF1b3RlZCIsICJjb3VudHJ5X2NvZGUiLCAiY291bnRyeSIsICJsYXQiLCAibG5nIikNCmNhbnRfdW5pcXVlIDwtIGMoIGxlbmd0aCh1bmlxdWUoZGZfbG9jYXRpb24kbG9jYXRpb24pKQ0KICAgICAgICAgICAgICAgICAgLGxlbmd0aCh1bmlxdWUoZGZfbG9jYXRpb24kcmV0d2VldF9sb2NhdGlvbikpDQogICAgICAgICAgICAgICAgICAsbGVuZ3RoKHVuaXF1ZShkZl9sb2NhdGlvbiRxdW90ZWRfbG9jYXRpb24pKQ0KICAgICAgICAgICAgICAgICAgLGxlbmd0aCh1bmlxdWUoZGZfbG9jYXRpb24kY291bnRyeV9jb2RlKSkNCiAgICAgICAgICAgICAgICAgICxsZW5ndGgodW5pcXVlKGRmX2xvY2F0aW9uJGNvdW50cnkpKQ0KICAgICAgICAgICAgICAgICAgLGxlbmd0aCh1bmlxdWUoZGZfbG9jYXRpb24kbGF0KSkNCiAgICAgICAgICAgICAgICAgICxsZW5ndGgodW5pcXVlKGRmX2xvY2F0aW9uJGxuZykpKQ0KY2FudF9uYSA8LSBjKCBucm93KGRmX2xvY2F0aW9uW2lzLm5hKGRmX2xvY2F0aW9uJGxvY2F0aW9uKSxdKQ0KICAgICAgICAgICAgICAsIG5yb3coZGZfbG9jYXRpb25baXMubmEoZGZfbG9jYXRpb24kcmV0d2VldF9sb2NhdGlvbiksXSkNCiAgICAgICAgICAgICAgLCBucm93KGRmX2xvY2F0aW9uW2lzLm5hKGRmX2xvY2F0aW9uJHF1b3RlZF9sb2NhdGlvbiksXSkNCiAgICAgICAgICAgICAgLCBucm93KGRmX2xvY2F0aW9uW2lzLm5hKGRmX2xvY2F0aW9uJGNvdW50cnlfY29kZSksXSkNCiAgICAgICAgICAgICAgLCBucm93KGRmX2xvY2F0aW9uW2lzLm5hKGRmX2xvY2F0aW9uJGNvdW50cnkpLF0pDQogICAgICAgICAgICAgICwgbnJvdyhkZl9sb2NhdGlvbltpcy5uYShkZl9sb2NhdGlvbiRsYXQpLF0pDQogICAgICAgICAgICAgICwgbnJvdyhkZl9sb2NhdGlvbltpcy5uYShkZl9sb2NhdGlvbiRsbmcpLF0pDQopDQpkZiA8LSBkby5jYWxsKHJiaW5kLCBNYXAoZGF0YS5mcmFtZSwgQT1ub21icmVfbG9jYXRpb24sIEI9Y2FudF91bmlxdWUsIEM9Y2FudF9uYSkpDQpuYW1lcyhkZilbMV0gPC0gIkF0cmlidXRvIg0KbmFtZXMoZGYpWzJdIDwtICJVbmlxdWUiDQpuYW1lcyhkZilbM10gPC0gIk5hIg0KDQpkZiRwb3JjZW50YWplX25hIDwtIGRmJE5hIC8gbnJvdyhkZl9sb2NhdGlvbikgKiAxMDANCmBgYA0KDQpgYGB7cn0NCg0KcG5nKGZpbGVuYW1lPSJsb2NhdGlvbl9wb3JjX25hLnBuZyIsIHdpZHRoPTEwMDAsIGJnPSJ3aGl0ZSIpDQpnZ3Bsb3QoZGYsIGFlcyh4PXJlb3JkZXIoQXRyaWJ1dG8sIHBvcmNlbnRhamVfbmEpLCB5PXBvcmNlbnRhamVfbmEsIGZpbGw9QXRyaWJ1dG8pKSArIA0KICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsNCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iU2V0MiIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICIiLA0KICAgIHN1YnRpdGxlID0gIiIsDQogICAgY2FwdGlvbiA9ICIiLA0KICAgIHRhZyA9ICIiDQogICkgKw0KICB4bGFiKCIiKSArDQogIHlsYWIoIiIpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIA0KICAgICAgICBheGlzLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTQpLA0KICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dCggbWFyZ2luID0gbWFyZ2luKDEwLCAxMCwgMTAsIDEwKSksDQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4odCA9IDEwLCByID0gMTAsIGIgPSAxMCwgbCA9IDEwKSksDQogICAgICAgIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTE0KSwNCiAgICAgICAgYXNwZWN0LnJhdGlvID0gMS8xDQogICkgKw0KICBjb29yZF9mbGlwKCkNCmRldi5vZmYoKQ0KDQpgYGANCg0KYGBge3J9DQoNCnBhaXNlc19lbiA8LSByZWFkLmNzdigiQzpcXFVzZXJzXFxMdWNhc1xcRGVza3RvcFxcMjAxOVxcRGF0YSBtaW5uaW5nXFxEYXRhTWluaW5nVWJhMjAyMFxcVHBzXFxUcDFcXGNvdW50cmllcy5lbi5jc3YiLCBoZWFkZXIgPSBULCBzZXAgPSAnOycpDQpwYWlzZXNfZXMgPC0gcmVhZC5jc3YoIkM6XFxVc2Vyc1xcTHVjYXNcXERlc2t0b3BcXDIwMTlcXERhdGEgbWlubmluZ1xcRGF0YU1pbmluZ1ViYTIwMjBcXFRwc1xcVHAxXFxjb3VudHJpZXMuZXMuY3N2IiwgaGVhZGVyID0gVCwgc2VwID0gJzsnKQ0KDQpgYGANCg0KYGBge3J9DQoNCmhlYWQocGFpc2VzX2VuKQ0KaGVhZChwYWlzZXNfZXMpDQpwYWlzZXNfZXMkUGFpcyA8LSB0cmltd3MocGFpc2VzX2VzJFBhaXMsIHdoaWNoID0gImJvdGgiKQ0KcGFpc2VzX2VzJENvZGlnbyA8LSB0cmltd3MocGFpc2VzX2VzJENvZGlnbywgd2hpY2ggPSAiYm90aCIpDQpwYWlzZXNfZXMkUmVnaW9uIDwtIHRyaW13cyhwYWlzZXNfZXMkUmVnaW9uLCB3aGljaCA9ICJib3RoIikNCnBhaXNlc19lcyRDb250aW5lbnRlIDwtIHRyaW13cyhwYWlzZXNfZXMkQ29udGluZW50ZSwgd2hpY2ggPSAiYm90aCIpDQpkZl9sb2NhdGlvbiRjb3VudHJ5XzIgPC0gZGZfbG9jYXRpb24kY291bnRyeQ0KZGZfbG9jYXRpb24kY291bnRyeV9jb2RlXzIgPC0gZGZfbG9jYXRpb24kY291bnRyeV9jb2RlDQoNCmBgYA0KDQpgYGB7cn0NCmZvcihpIGluIHBhaXNlc19lbiROQU1FKXsNCiAgcHJpbnQoaSkNCiAgZGZfbG9jYXRpb24kY291bnRyeV8yIDwtIGlmZWxzZShncmVwbCh0b2xvd2VyKGkpLCB0b2xvd2VyKGRmX2xvY2F0aW9uJGxvY2F0aW9uKSwgZml4ZWQ9IFQpLCB0b2xvd2VyKGkpLCBkZl9sb2NhdGlvbiRjb3VudHJ5XzIpDQp9DQoNCg0KZm9yKGkgaW4gcGFpc2VzX2VuJE5BTUUpew0KICBwcmludChpKQ0KICBpZiAobnJvdyhkZl9sb2NhdGlvblshaXMubmEoZGZfbG9jYXRpb24kY291bnRyeV8yKSAmIGRmX2xvY2F0aW9uJGNvdW50cnlfMiA9PSB0b2xvd2VyKGkpLF0pID4gMCkgew0KICAgICMgZGZfbG9jYXRpb24kY291bnRyeV9jb2RlXzJbIWlzLm5hKGRmX2xvY2F0aW9uJGNvdW50cnlfMikgJiBkZl9sb2NhdGlvbiRjb3VudHJ5XzIgPT0gdG9sb3dlcignc3BhaW4nKV0gPC0gYXMuY2hhcmFjdGVyLmZhY3RvcihwYWlzZXNfZW4kSVNPW3BhaXNlc19lbiROQU1FID09ICdTUEFJTiddKQ0KICAgICMgZGZfbG9jYXRpb24kY291bnRyeV9jb2RlXzJbIWlzLm5hKGRmX2xvY2F0aW9uJGNvdW50cnlfMikgJiBkZl9sb2NhdGlvbiRjb3VudHJ5XzIgPT0gdG9sb3dlcihpKV0gPC0gYXMuY2hhcmFjdGVyLmZhY3RvcihwYWlzZXNfZW4kSVNPW3BhaXNlc19lbiROQU1FID09IGldKQ0KICAgIGRmX2xvY2F0aW9uWyFpcy5uYShkZl9sb2NhdGlvbiRjb3VudHJ5XzIpICYgZGZfbG9jYXRpb24kY291bnRyeV8yID09IHRvbG93ZXIoaSksXSRjb3VudHJ5X2NvZGVfMiA8LSBwYWlzZXNfZW4kSVNPW3BhaXNlc19lbiROQU1FID09IGldDQogIH0NCn0NCmBgYA0KDQoNCmBgYHtyfQ0KZm9yKGkgaW4gcGFpc2VzX2VzJFBhaXMpew0KICBwcmludChpKQ0KICAjIGlmZWxzZShncmVwbCgiQXJnZW50aW5hIiwgZGZfbG9jYXRpb24kbG9jYXRpb24sIGZpeGVkPSBUKSwgIkFyZ2VudGluYSIsICIiKQ0KICBkZl9sb2NhdGlvbiRjb3VudHJ5XzIgPC0gaWZlbHNlKGdyZXBsKHRvbG93ZXIoaSksIHRvbG93ZXIoZGZfbG9jYXRpb24kbG9jYXRpb24pLCBmaXhlZD0gVCksIHRvbG93ZXIoaSksIGRmX2xvY2F0aW9uJGNvdW50cnlfMikNCn0NCg0KZm9yKGkgaW4gcGFpc2VzX2VzJFBhaXMpew0KICBwcmludChpKQ0KICBpZiAobnJvdyhkZl9sb2NhdGlvblshaXMubmEoZGZfbG9jYXRpb24kY291bnRyeV8yKSAmIGRmX2xvY2F0aW9uJGNvdW50cnlfMiA9PSB0b2xvd2VyKGkpLF0pID4gMCkgew0KICAgICMgZGZfbG9jYXRpb24kY291bnRyeV9jb2RlXzJbIWlzLm5hKGRmX2xvY2F0aW9uJGNvdW50cnlfMikgJiBkZl9sb2NhdGlvbiRjb3VudHJ5XzIgPT0gdG9sb3dlcignc3BhaW4nKV0gPC0gYXMuY2hhcmFjdGVyLmZhY3RvcihwYWlzZXNfZW4kSVNPW3BhaXNlc19lbiROQU1FID09ICdTUEFJTiddKQ0KICAgICMgZGZfbG9jYXRpb24kY291bnRyeV9jb2RlXzJbIWlzLm5hKGRmX2xvY2F0aW9uJGNvdW50cnlfMikgJiBkZl9sb2NhdGlvbiRjb3VudHJ5XzIgPT0gdG9sb3dlcihpKV0gPC0gYXMuY2hhcmFjdGVyLmZhY3RvcihwYWlzZXNfZW4kSVNPW3BhaXNlc19lbiROQU1FID09IGldKQ0KICAgIGRmX2xvY2F0aW9uWyFpcy5uYShkZl9sb2NhdGlvbiRjb3VudHJ5XzIpICYgZGZfbG9jYXRpb24kY291bnRyeV8yID09IHRvbG93ZXIoaSksXSRjb3VudHJ5X2NvZGVfMiA8LSBwYWlzZXNfZXMkQ29kaWdvW3BhaXNlc19lcyRQYWlzID09IGldDQogIH0NCiAgIyBkZl9sb2NhdGlvbiRjb3VudHJ5X2NvZGVfMlshaXMubmEoZGZfbG9jYXRpb24kY291bnRyeV8yKSAmIGRmX2xvY2F0aW9uJGNvdW50cnlfMiA9PSB0b2xvd2VyKGkpXSA8LSBhcy5jaGFyYWN0ZXIuZmFjdG9yKHBhaXNlc19lcyRDb2RpZ29bcGFpc2VzX2VzJFBhaXMgPT0gaV0pDQp9DQpgYGANCg0KI1VuaW1vcyBjb250aW5lbnRlDQpgYGB7cn0NCg0KZm9yKGkgaW4gcGFpc2VzX2VzJENvZGlnbyl7DQogIHByaW50KGkpDQogIGRmX2xvY2F0aW9uJFJlZ2lvblshaXMubmEoZGZfbG9jYXRpb24kY291bnRyeV9jb2RlXzIpICYgZGZfbG9jYXRpb24kY291bnRyeV9jb2RlXzIgPT0gaV0gPC0gcGFpc2VzX2VzJFJlZ2lvbltwYWlzZXNfZXMkQ29kaWdvID09IGldDQogIGRmX2xvY2F0aW9uJENvbnRpbmVudGVbIWlzLm5hKGRmX2xvY2F0aW9uJGNvdW50cnlfY29kZV8yKSAmIGRmX2xvY2F0aW9uJGNvdW50cnlfY29kZV8yID09IGldIDwtIHBhaXNlc19lcyRDb250aW5lbnRlW3BhaXNlc19lcyRDb2RpZ28gPT0gaV0NCn0NCmBgYA0KDQpgYGB7cn0NCg0KDQphdXggPC0gZGF0YS5mcmFtZSh0YWJsZShkZl9sb2NhdGlvbiRDb250aW5lbnRlKSkNCm5hbWVzKGF1eCkgPC0gYygiQ29udGluZW50ZSIsICJGcmVjdWVuY2lhIikNCmF1eA0KcG5nKGZpbGVuYW1lPSJsb2NhdGlvbl9wb3JjX25hLnBuZyIsIHdpZHRoPTEwMDAsIGJnPSJ3aGl0ZSIpDQogIGdncGxvdChhdXgsIGFlcyh4PXJlb3JkZXIoQ29udGluZW50ZSwgRnJlY3VlbmNpYSksIHk9RnJlY3VlbmNpYSwgZmlsbD1Db250aW5lbnRlKSkgKyANCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsNCiAgICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJTZXQyIikgKw0KICAgIGxhYnMoDQogICAgICB0aXRsZSA9ICIiLA0KICAgICAgc3VidGl0bGUgPSAiIiwNCiAgICAgIGNhcHRpb24gPSAiIiwNCiAgICAgIHRhZyA9ICIiDQogICAgKSArDQogICAgeGxhYigiIikgKw0KICAgIHlsYWIoIiIpICsNCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgDQogICAgICAgICAgYXhpcy50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTE0KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dCggbWFyZ2luID0gbWFyZ2luKDEwLCAxMCwgMTAsIDEwKSksDQogICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbih0ID0gMTAsIHIgPSAxMCwgYiA9IDEwLCBsID0gMTApKSwNCiAgICAgICAgICBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xNCksDQogICAgICAgICAgYXNwZWN0LnJhdGlvID0gMS8xDQogICAgKSArDQogICAgY29vcmRfZmxpcCgpDQpkZXYub2ZmKCkNCmBgYA0KDQoNCiMjIENsYXNpZmljYXIgZW4gbm90aWNpYXMgLSBwb2xpdGljYSAtIG90cm9zDQoNCmBgYHtyfQ0KDQp0IDwtIG1vbmdvKGNvbGxlY3Rpb24gPSAidHdlZXRzX2xvd2VyIiwgZGIgPSAiRE1VQkEiKQ0KYXV4IDwtIHQkYWdncmVnYXRlKCdbeyIkcHJvamVjdCI6eyJfaWQiOiAiJF9pZCIsInVzZXJfaWQiOiIkdXNlcl9pZCIsInNjcmVlbl9uYW1lIjoiJHNjcmVlbl9uYW1lIiwidGV4dCI6IiRkZXNjcmlwdGlvbiJ9fV0nKQ0KYGBgDQoNCmBgYHtyfQ0KYXV4JHRleHQgPC0gdG9sb3dlcihhdXgkdGV4dCkNCmF1eCR0ZXh0IDwtIGdzdWIoImh0dHAuKiIsIiIsYXV4JHRleHQpDQphdXgkdGV4dCA8LSBnc3ViKCJodHRwcy4qIiwiIixhdXgkdGV4dCkNCg0KIyAjUXVpdGFuZG8gbG9zIGhhc2h0YWdzIHkgdXN1YXJpb3MgZW4gbG9zIHR3ZWV0c190ZXh0DQojIGF1eCR0ZXh0IDwtIGdzdWIoIiNcXHcrIiwiIixhdXgkdGV4dCkNCmF1eCR0ZXh0IDwtIGdzdWIoIkBcXHcrIiwiIixhdXgkdGV4dCkNCg0KYXV4JHRleHQgPC0gZ3N1YigiW1s6cHVuY3Q6XV0iLCIiLGF1eCR0ZXh0KQ0KYXV4JHRleHQgPC0gZ3N1YigiXFx3KlswLTldK1xcdypcXHMqIiwgIiIsYXV4JHRleHQpDQoNCmF1eCR0ZXh0IDwtIGdzdWIoIltbOnB1bmN0Ol1dIiwiIixhdXgkdGV4dCkNCmF1eCR0ZXh0IDwtIGdzdWIoIlteWzphbG51bTpdWzpibGFuazpdPyYvXFwtXSIsICIiLCBhdXgkdGV4dCkNCmF1eCR0ZXh0IDwtIGljb252KGF1eCR0ZXh0LGZyb209IlVURi04Iix0bz0iQVNDSUkvL1RSQU5TTElUIikNCiAgDQpwYWxhYnJhc19ub3RpY2lhcyA8LSBjKCJub3RpY2lhIiwgInBlcmlvZGlzbW8iLCAicGVyaW9kaXN0YSIsICdwZXJpb2RpY28nLCAibmV3cyIsICdqb3VybmFsaXN0JywgInJlcG9ydGVybyIsICJwcm9ncmFtYSBkZSB0diIsICd0ZWxldmlzaW9uJywgJ1JldXRlcnMgJywgJ2VscGFpc2FtZXJpY2EnLCAncHJvZHVjdG9yYScsICdjb25kdWN0b3InLCAnY29sdW1uaXN0YScsICdjb3JyZXNwb25zYWwnLCAndGVsZXN1cicpDQphdXgkaXNfbmV3c19yZWxhdGVkIDwtIEYNCmZvciAoaSBpbiBwYWxhYnJhc19ub3RpY2lhcykgew0KICBhdXgkaXNfbmV3c19yZWxhdGVkIDwtIGlmZWxzZShncmVwbChpLCBhdXgkdGV4dCwgZml4ZWQ9IFQpLCBULCBhdXgkaXNfbmV3c19yZWxhdGVkKQ0KfQ0KcGFsYWJyYXNfcG9saXRpY2EgPC0gYygicG9saXRpY28iLCAic2VuYWRvciIsICJkaXB1dGFkbyIsICJhbGNhbGRlIiwgInN1YnNlY3JldGFyaW8iLCAic2VjcmV0YXJpbyIsICJzZWNyZXRhcmlhIiwgInByZXNpZGVuY2lhIiwgInByZXNpZGVudGUiLCAibWluaXN0ZXJpbyIsICJtaW5pc3RybyIsICJtaW5pc3RyYSIsICJww7pibGljbyIsICJwdWJsaWNvIiwgImNhbmNpbGxlciIsICJQYXJ0aWRvIFNvY2lhbGlzdGEiLCAiUFNVViIsICJwYXJ0aWRvIGRlbCBwdWVibG8iLCAnYXNhbWJsZWEgbmFjaW9uYWwnKQ0KYXV4JGlzX3BvbGl0aWNfcmVsYXRlZCA8LSBGDQpmb3IgKGkgaW4gcGFsYWJyYXNfcG9saXRpY2EpIHsNCiAgYXV4JGlzX3BvbGl0aWNfcmVsYXRlZCA8LSBpZmVsc2UoZ3JlcGwoaSwgYXV4JHRleHQsIGZpeGVkPSBUKSwgVCwgYXV4JGlzX3BvbGl0aWNfcmVsYXRlZCkNCn0NCmBgYA0KDQpgYGB7cn0NCiMgYmFycGxvdCh0d2VldHMkaXNfbmV3c19yZWxhdGVkKQ0KIyBiYXJwbG90KHR3ZWV0cyRpc19wb2xpdGljX3JlbGF0ZWQpDQpgYGANCg0KYGBge3J9DQphdXgkdGlwb191c2VyID0gIk5vcm1hbCINCmF1eFthdXgkaXNfbmV3c19yZWxhdGVkLF0kdGlwb191c2VyIDwtICJNZWRpbyINCmF1eFthdXgkaXNfcG9saXRpY19yZWxhdGVkLF0kdGlwb191c2VyIDwtICJQb2xpdGljYSINCmF1eCRpc19uZXdzX3JlbGF0ZWQgPC0gTlVMTA0KYXV4JGlzX3BvbGl0aWNfcmVsYXRlZCA8LSBOVUxMDQphdXgkdGV4dCA8LSBOVUxMDQoNCmF1eFthdXgkdGlwb191c2VyPT0nUG9saXRpY2EnLF0NCiMgdHdlZXRzIDwtIG1lcmdlKHR3ZWV0cywgYXV4LCBieT0idHdlZXRfaWQiKQ0KYXV4ICU+JSBncm91cF9ieShzY3JlZW5fbmFtZSkgJT4lIHN1bW1hcmlzZSh0aXBvID0gbWF4KHRpcG9fdXNlcikpDQojIHRhYmxlKGF1eCR0aXBvX3VzZXIpDQpgYGANCg0KDQpgYGB7cn0NCnVzZXIgPC0gYXV4ICU+JSBzZWxlY3QoJ19pZCcsICd1c2VyX2lkJywgJ3NjcmVlbl9uYW1lJywgJ3RpcG9fdXNlcicpDQpgYGANCg0KDQoNCmBgYHtyfQ0KYXV4IDwtIHQkYWdncmVnYXRlKCdbeyIkcHJvamVjdCI6eyJfaWQiOiIkX2lkIiwidXNlcl9pZCI6IiRyZXR3ZWV0X3VzZXJfaWQiLCJzY3JlZW5fbmFtZSI6IiRyZXR3ZWV0X3NjcmVlbl9uYW1lIiwidGV4dCI6IiRyZXR3ZWV0X2Rlc2NyaXB0aW9uIn19XScpDQphdXggPC0gYXV4WyFpcy5uYShhdXgkc2NyZWVuX25hbWUpLF0NCmBgYA0KDQpgYGB7cn0NCmF1eCR0ZXh0IDwtIHRvbG93ZXIoYXV4JHRleHQpDQphdXgkdGV4dCA8LSBnc3ViKCJodHRwLioiLCIiLGF1eCR0ZXh0KQ0KYXV4JHRleHQgPC0gZ3N1YigiaHR0cHMuKiIsIiIsYXV4JHRleHQpDQoNCiMgI1F1aXRhbmRvIGxvcyBoYXNodGFncyB5IHVzdWFyaW9zIGVuIGxvcyB0d2VldHNfdGV4dA0KIyBhdXgkdGV4dCA8LSBnc3ViKCIjXFx3KyIsIiIsYXV4JHRleHQpDQphdXgkdGV4dCA8LSBnc3ViKCJAXFx3KyIsIiIsYXV4JHRleHQpDQoNCmF1eCR0ZXh0IDwtIGdzdWIoIltbOnB1bmN0Ol1dIiwiIixhdXgkdGV4dCkNCmF1eCR0ZXh0IDwtIGdzdWIoIlxcdypbMC05XStcXHcqXFxzKiIsICIiLGF1eCR0ZXh0KQ0KDQphdXgkdGV4dCA8LSBnc3ViKCJbWzpwdW5jdDpdXSIsIiIsYXV4JHRleHQpDQphdXgkdGV4dCA8LSBnc3ViKCJbXls6YWxudW06XVs6Ymxhbms6XT8mL1xcLV0iLCAiIiwgYXV4JHRleHQpDQphdXgkdGV4dCA8LSBpY29udihhdXgkdGV4dCxmcm9tPSJVVEYtOCIsdG89IkFTQ0lJLy9UUkFOU0xJVCIpDQogIA0KcGFsYWJyYXNfbm90aWNpYXMgPC0gYygibm90aWNpYSIsICJwZXJpb2Rpc21vIiwgInBlcmlvZGlzdGEiLCAncGVyaW9kaWNvJywgIm5ld3MiLCAnam91cm5hbGlzdCcsICJyZXBvcnRlcm8iLCAicHJvZ3JhbWEgZGUgdHYiLCAndGVsZXZpc2lvbicsICdSZXV0ZXJzICcsICdlbHBhaXNhbWVyaWNhJywgJ3Byb2R1Y3RvcmEnLCAnY29uZHVjdG9yJywgJ2NvbHVtbmlzdGEnLCAnY29ycmVzcG9uc2FsJywgJ3RlbGVzdXInKQ0KYXV4JGlzX25ld3NfcmVsYXRlZCA8LSBGDQpmb3IgKGkgaW4gcGFsYWJyYXNfbm90aWNpYXMpIHsNCiAgYXV4JGlzX25ld3NfcmVsYXRlZCA8LSBpZmVsc2UoZ3JlcGwoaSwgYXV4JHRleHQsIGZpeGVkPSBUKSwgVCwgYXV4JGlzX25ld3NfcmVsYXRlZCkNCn0NCnBhbGFicmFzX3BvbGl0aWNhIDwtIGMoInBvbGl0aWNvIiwgInNlbmFkb3IiLCAiZGlwdXRhZG8iLCAiYWxjYWxkZSIsICJzdWJzZWNyZXRhcmlvIiwgInNlY3JldGFyaW8iLCAic2VjcmV0YXJpYSIsICJwcmVzaWRlbmNpYSIsICJwcmVzaWRlbnRlIiwgIm1pbmlzdGVyaW8iLCAibWluaXN0cm8iLCAibWluaXN0cmEiLCAicMO6YmxpY28iLCAicHVibGljbyIsICJjYW5jaWxsZXIiLCAiUGFydGlkbyBTb2NpYWxpc3RhIiwgIlBTVVYiLCAicGFydGlkbyBkZWwgcHVlYmxvIiwgJ2FzYW1ibGVhIG5hY2lvbmFsJykNCmF1eCRpc19wb2xpdGljX3JlbGF0ZWQgPC0gRg0KZm9yIChpIGluIHBhbGFicmFzX3BvbGl0aWNhKSB7DQogIGF1eCRpc19wb2xpdGljX3JlbGF0ZWQgPC0gaWZlbHNlKGdyZXBsKGksIGF1eCR0ZXh0LCBmaXhlZD0gVCksIFQsIGF1eCRpc19wb2xpdGljX3JlbGF0ZWQpDQp9DQpgYGANCg0KYGBge3J9DQojIGJhcnBsb3QodHdlZXRzJGlzX25ld3NfcmVsYXRlZCkNCiMgYmFycGxvdCh0d2VldHMkaXNfcG9saXRpY19yZWxhdGVkKQ0KYGBgDQoNCmBgYHtyfQ0KYXV4JHRpcG9fdXNlciA9ICJOb3JtYWwiDQphdXhbYXV4JGlzX25ld3NfcmVsYXRlZCxdJHRpcG9fdXNlciA8LSAiTWVkaW8iDQphdXhbYXV4JGlzX3BvbGl0aWNfcmVsYXRlZCxdJHRpcG9fdXNlciA8LSAiUG9saXRpY2EiDQphdXgkaXNfbmV3c19yZWxhdGVkIDwtIE5VTEwNCmF1eCRpc19wb2xpdGljX3JlbGF0ZWQgPC0gTlVMTA0KYXV4JHRleHQgPC0gTlVMTA0KDQphdXhbYXV4JHRpcG9fdXNlcj09J1BvbGl0aWNhJyxdDQojIHR3ZWV0cyA8LSBtZXJnZSh0d2VldHMsIGF1eCwgYnk9InR3ZWV0X2lkIikNCmF1eCAlPiUgZ3JvdXBfYnkoc2NyZWVuX25hbWUpICU+JSBzdW1tYXJpc2UodGlwbyA9IG1heCh0aXBvX3VzZXIpKQ0KIyB0YWJsZShhdXgkdGlwb191c2VyKQ0KDQpgYGANCg0KDQoNCmBgYHtyfQ0KbmFtZXModXNlcikgPC0gYygiX2lkIiwgInVzZXJfaWQiLCAic2NyZWVuX25hbWUiLCAidGlwb191c2VyIikNCm5hbWVzKGF1eCkgPC0gYygiX2lkIiwgInVzZXJfaWQiLCAic2NyZWVuX25hbWUiLCAidGlwb191c2VyIikNCnVzZXIgPC0gcmJpbmQodXNlciwgYXV4KQ0KYGBgDQoNCg0KDQoNCg==